父DOM节点更改类型时的ReactJS协调

时间:2017-08-16 11:01:37

标签: javascript reactjs

组件呈现以下React元素树。

<div>
  <Counter />
</div>

然后发生状态或道具更改并触发渲染,从而生成以下React元素树。

<span>
  <Counter />
</span>

Counter组件的实例是否会被完全重新实例化,构造函数和所有组件?

如果是这样,这种相同的行为是否适用于非根节点,例如:

<div>
  <div>
    <Counter />
  </div>
</div>

过渡到......

<div>
  <span>
    <Counter />
  </span>
</div>

2 个答案:

答案 0 :(得分:1)

是的,它将在

上重新实例化Couter组件
<div>
  <Counter />
</div>

<span>
  <Counter />
</span>

Reconciliation中指定的流程说:

  

这将摧毁旧柜台并重新安装新柜台。

对于第二个示例,它将首先比较<div>,但没有变化,但下一个是与上面相同的情况,因此它也remount Counter组件。

答案 1 :(得分:0)

From the docs

  

每当根元素具有不同类型时,React将会拆除   旧树和从头开始构建新树。从<a>开始   <img>,或<Article><Comment>,或<Button><div> - any   这些将导致完全重建。

所以是的,在这两种情况下,具有新类型的节点下面的所有内容都将被完全重建。

工作演示

class Inner extends React.Component {
    constructor(props) {
        super(props);
        console.log('Inner constructor called.')
    }

    render() {
        return <p>{`<${this.props.tag}>`}</p>;
    }
}

const Container = ({Tag}) => (
    <Tag>
        <Inner tag={Tag} />
    </Tag>
);

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            tag: 'div',
        };
    }

    changeTag = () => this.setState(state => state.tag === 'div' ? {tag: 'span'} : {tag: 'div'});

    render() {
        return (
            <div>
                <button onClick={this.changeTag}>Change tag</button>
                <Container Tag={this.state.tag} />
            </div>
        );
    }
}

ReactDOM.render(<App />, document.getElementById('root'));
<div id="root"><!--Filled by React--></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>