【问题标题】:Adding tab dynamically upgradeElement动态添加选项卡 upgradeElement
【发布时间】:2015-11-06 09:53:45
【问题描述】:

当我添加一个带有 react 的选项卡时,它的父元素已经升级了。所以调用 upgradElement 没有任何效果,添加的选项卡也不起作用。 什么解决方案,用容器重新创建所有选项卡并升级它? React 只是更新 DOM 组件,在这种情况下我需要卸载组件?

【问题讨论】:

    标签: javascript reactjs material-design-lite


    【解决方案1】:

    具体组件的componentDidUpdate阶段调用componentHandler.upgradeElement()或者componentHandler.upgradeDom()怎么样

        componentDidUpdate() {
            componentHandler.upgradeElement(this.refs.myElement);
            //or componentHandler.upgradeDom('MaterialTabs');
        }
    

    编辑 1 个选项卡组件

        componentDidUpdate() {
    
            componentHandler.upgradeDom();
        }
    
        newTab() {
            this.setState({
                newtab: 1
            });
        }
    
        render() {
    
            return (<div className="mdl-layout mdl-js-layout mdl-layout--fixed-header" key={this.state.newtab}>
                <button onClick={this.newTab.bind(this)}>Add Tab</button>
                    <header className="mdl-layout__header">
                        <div className="mdl-layout__tab-bar mdl-js-ripple-effect">
                            <Link to="/tabtest" hash="#scroll-tab-1" className="mdl-layout__tab is-active">Tab 1</Link>
                            <Link to="/tabtest" hash="#scroll-tab-2" className="mdl-layout__tab">Tab 2</Link>
                            { this.state.newtab ?
                            <Link to="/tabtest" hash="#scroll-tab-3" className="mdl-layout__tab">Tab 3</Link> : null}
                        </div>
                    </header>
                <div className="mdl-layout__content">
                    <section className="mdl-layout__tab-panel is-active" id="scroll-tab-1">
                        <div className="page-content">Tab 1</div>
                    </section>
                    <section className="mdl-layout__tab-panel" id="scroll-tab-2">
                        <div className="page-content">Tab 2</div>
                    </section>
                    { this.state.newtab ? <section className="mdl-layout__tab-panel" id="scroll-tab-3">
                        <div className="page-content">Tab 2</div>
                    </section> : null}
                </div>
            </div>);
    
        }
    

    我做了一些测试,可以重现问题。有帮助的是将 key 属性放在选项卡组件的根元素上。添加新选项卡时,此键必须更改,并且 react 将丢弃组件并完全重新渲染。这样,所有 material-design-lite 属性都会丢失,并且在调用 upgradeDom 或 upgradeElement 后它可以工作。

    React and Material-Design-Lite

    Material-Design-Lite source

    【讨论】:

    • 这就是我所做的,调用 componentHandler.upgradeDom() 但它什么也没做,因为我认为 TabContainer 已经升级,所以它不会深入 dom。我会尝试 upgradeElement 特定的选项卡...
    • 事实上 tabs 元素不是 ugradable 元素,这是 div 容器,它是 ugradable 并且它已经升级了。所以我不知道如何强制升级元素。
    • 好的,那么当您添加选项卡时,您必须在选项卡容器上使用 forceUpdate,然后调用 this.upgradeElement。我自己也试试。
    • 我不需要强制更新,DOM 是更新的,但是在 upgradeElement 不做这项工作之后,我尝试降级和升级,但它仍然不起作用。
    • 更新了我的答案,让它工作。我希望它可以帮助你继续。
    【解决方案2】:

    来自https://facebook.github.io/react/docs/component-api.html

    强制更新

    无效力更新( [函数回调] )

    默认情况下,当你的组件状态或道具改变时,你的组件会重新渲染。但是,如果这些变化是隐式的(例如:对象深处的数据发生变化而不改变对象本身),或者如果你的 render() 方法依赖于一些其他数据,你可以告诉 React 它需要通过调用重新运行 render()强制更新()。

    调用 forceUpdate() 将导致在组件上调用 render(),跳过 shouldComponentUpdate()。这将触发子组件的正常生命周期方法,包括每个子组件的 shouldComponentUpdate() 方法。如果标记发生变化,React 仍然只会更新 DOM。

    通常你应该尽量避免使用 forceUpdate() 并且只在 render() 中读取 this.props 和 this.state。这使您的组件“纯粹”并且您的应用程序更加简单和高效。

    【讨论】:

    • 我同意但反应更新 dom 但 MDL 已升级它,因此新选项卡已呈现但 MDL 选项卡容器已标记已升级,因此新选项卡无法正常工作。我需要将所有组件 dom 重新创建为其初始状态(在 MDL 升级之前)。
    • 我想我需要在 componentWillUnmount 函数中降级 DOM。 MDL 有这个功能吗?
    • 我不使用MDL所以不知道。
    【解决方案3】:

    为了突出 Christian Steinmann 回答中最重要的部分:

    将周围的.mdl-js-tabs div 元素的标签算作key 属性。

    每当添加一个选项卡时,键都会改变,React 将重新渲染整个选项卡组件。这将随后 MDL 升级。

    【讨论】:

      最近更新 更多