大佬博客:https://react.iamkasong.com/diff/one.html#%E7%BB%83%E4%B9%A0%E9%A2%98
参考视频:
https://www.bilibili.com/video/BV1uh411177Q
https://www.bilibili.com/video/BV16t4y1r7oJ
https://www.bilibili.com/video/BV1Ki4y1u7Vr
this.setState会产生,在render和commit阶段,会调用所有的组件生命周期函数。
1 首次渲染。:组件挂载:
render阶段, commit阶段。
1 调用ReactDOM。render。2 进入 render阶段。3 采用 深度优先遍历 创建fiber树(虚拟DOM树)
App (construetor ,willMount, render)
p1 深度有先
c1
c2
p2
渲染到界面上。
4 commit阶段
从子节点,componentDidMount 执行C1 didmount,c2 ->p1-> p2->app。
2 组件更新。!!!这才使用了diff算法的核心!!!
1 this.setState,c2变成绿色。(每一次调用setState都会创建出完整的fiber树)
2 进入render阶段。
3 采用深度优先遍历,创建fiber树。
4 节点没有更新,则不需要调用生命周期函数。节点更新了,则调用 reconcile算法,标记变换!调用c2对应的生命周期函数。
render阶段完成后,进入cmmit阶段,执行4变化的试图函数。
(新创建的fiber树会替换掉之前的fiber树。)
1 对比虚拟DOM树。 怎么对比这个虚拟DOM树呢?
1 看key是否相同?k未设置的话,key默认为null,key改变,不需要判断type,直接不能复用。
2 看type 。看标签,如果标签不同,则直接销毁,然后新建一个dom树。
3 如果属性不同,则不会销毁,而是修改。
React渲染流程:
JSX->虚拟DOM, ->真实DOM
React更新流程。
props、state改变,render函数重新执行, 产生新的dom树,dom树进行新的diff, 计算出差异进行更新, 更新的真实的dom。
情况1 对比不同类型的元素。
a->img ,button->div, Ariticle ->compmonet 会触发一个完整的重建流程。
1当卸载一颗树的时候,对应的DOM节点也会被销毁,组件实例将执行componentWillUnmount()方法。
2 建立一颗新树,对应的DOM节点被创建插入到DOM中,组件实例执行componentWillMount()方法。DidMount方法
<div><Count/></div>
<span><Count/><span>
即使Count组件一样,span也是不同。
情况2 对比同一类型元素的元素。
div className=“before” title=‘sstuff’
div className ="before" title ="stuff"
style {{ solor:'red',fontWeight:'bold' }}
style {{ solor:'green',fontWeight:'bold' }}
如果相同类型的reac元素,会保存DOM节点,仅仅对比新有的属性。
情况3 对子节点 进行递归。
产生差异,生成一个mutation,查到底部DOM树就可以了。
但是如果中间插入一个数据,性能就很低,
keys进行优化。
react 的性能优化!
PureComponent