深入理解React的Virtual DOM(3)
▌Case 2:type仍然是相同的字符串,props是不同的。
由于type仍然代表一个HTML元素,React知道如何通过标准的DOM API调用更改其属性,而无需从DOM树中删除节点。 ▌Case 3:type已更改为不同的组件String或从String组件更改为组件。
由于React现在看到类型不同,它甚至不会尝试更新DOM节点:旧元素将与其所有子节点一起被删除(unmount)。因此,在DOM树上替换完全不同的元素的代价会非常之高。幸运的是,这在实际情况中很少发生。 重要的是要记住React使用===(三等)来比较type值,因此它们必须是同一个类或相同函数的相同实例。 下一个场景更有趣,因为这是开发者最常使用React的方式。 ▌Case 4:type是一个组件。
你可能会说,“这好像没有任何变化”,但这是不对的。 如果type是对函数或类的引用(即常规React组件),并且启动了树diff比较过程,那么React将始终尝试查看组件内部的所有child以确保render的返回值没有更改。即在树下比较每个组件 - 是的,复杂的渲染也可能变得昂贵! 组件中的children 除了上面描述的四种常见场景之外,当元素有多个子元素时,开发者还需要考虑React的行为。假设有这样一个元素:
开发者开发者想将它重新渲染成这样(span和div交换了位置):
那么会发生什么? 当React看到里面的任何数组类型的props.children,它会开始将它中的元素与之前看到的数组中的元素按顺序进行比较:index 0将与index 0,index 1与index 1进行比较,对于每对子元素,React将应用上述规则集进行比较更新。在以上的例子中,它看到div变成一个span这是一个情景3中的情况。但这有一个问题:假设开发者想要从1000行表中删除第一行。React必须“更新”剩余的999个孩子,因为如果与先前的逐个索引表示相比,他们的内容现在将不相等。 幸运的是,React有一种内置的方法来解决这个问题。如果元素具有key属性,则元素将通过key而不是索引进行比较。只要key是唯一的,React就会移动元素而不将它们从DOM树中移除,然后将它们放回(React中称为挂载/卸载的过程)。
当状态改变时 到目前为止,本文只触及了props,React哲学的一部分,但忽略了state。这是一个简单的“有状态”组件:
现在,上述例子中的state对象有一个counter属性。单击按钮会增加其值并更改按钮文本。但是当用户点击时,DOM会发生什么?它的哪一部分将被重新计算和更新? 调用this.setState也会导致重新渲染,但不会导致整个页面重渲染,而只会导致组件本身及其子项。父母和兄弟姐妹都可以幸免于难。 修复问题 本文准备了一个DEMO,这是修复问题前的样子。你可以在这里查看其源代码。不过在此之前,你还需要安装React Developer Tools。 (编辑:ASP站长网) |