引入
- 多个React组件中,React组件也要考虑三个阶段:装载阶段、更新阶段和卸载阶段。
- 装载阶段:从这个React组件往下的所有子组件,都要经历一遍React组件的装载生命周期,因为这部分的工作没有什么可以省略的。
- 卸载阶段:只有一个生命周期函数componentWillUnmount,这个函数做的事情只是清理componentDidMount添加的事件处理监听等收尾工作,也没有什么可优化的空间。
React的调和(Reconciliation)过程
- 调和:React在更新阶段很巧妙地对比原有的Virtual DOM和新生成的VirtualDOM,找出两者的不同之处,根据不同来修改DOM树
React的Reconciliation算法
- 从根节点开始递归向下对比,首先检查两个树形的根节点类型是否相同
- 节点类型不同:直接认为原来那个树形结构已经没用,可以扔掉,需要重新构建新的DOM树,原有的树形上的React组件会经历“卸载”的生命周期。
所以要避免作为包裹功能的节点类型被随意改变
- 节点类型相同的情况
节点的类型可以分为两类:一类是DOM元素类型,对应的就是HTML直接支持的元素类型,比如div、span和p;另一类是React组件,也就是利用React库定制的类型
对于DOM元素类型,React会保留节点对应的DOM元素,只对树形结构根节点上的属性和内容做一下比对,然后只更新修改的部分
如果时React组件类型,React能做的只是根据新节点的props去更新原来根节点的组件实例,引发这个组件实例的更新过程。在这个过程中,如果shouldComponentUpdate函数返回false的话,那么更新过程就此打住,不再继续
- 多个子组件的情况
React会首先认为把text为First的TodoItem组件实例的text改成了Zero, text为Second的TodoItem组件实例的text改成了First,在最后面多出了一个TodoItem组件实例,text内容为Second。这样操作的后果就是,现存的两个TodoItem实例的text属性被改变了,强迫它们完成一个更新过程,创造出来的新的TodoItem实例用来显示Second
Key的用法
- Key属性,每个组件的身份证号
- React会提醒开发者不要忘记使用key,同类型子组件出现多个实例时如果没有key的话,React在运行时会给出警告
- key值只是唯一还不足够,这个key值还需要是稳定不变的
如果通过数组来产生一组子组件,一个常见的错误就是将元素在数组中的下标值作为key
- 需要注意,虽然key是一个prop,但是接受key的组件并不能读取到key的值,因为key和ref是React保留的两个特殊prop,并没有预期让组件直接访问。