请选择 进入手机版 | 继续访问电脑版

网赚研究院-致富网赚论坛-网赚宝盒-华夏网赚论坛-28网赚-贵族网赚论坛-日付网赚联盟

 找回密码
 立即注册
查看: 105|回复: 0

神气宝贝贪财妈 一文完全搞懂react的diff算法 万卷书屋网

发表于 2020-1-14 18:57 | 1050 显示全部楼层 |阅读模式

[复制链接]

2万

主题

4万

帖子

8万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
86839
发表于 2020-1-14 18:57 | 显示全部楼层 |阅读模式
这是写在帖子头部的内容
一文完全搞懂react的diff算法  新闻




React采纳声明式的API描摹UI结构,每次组件的状态或属性更新,组件的render方式城市返回一个新的捏造DOM工具,用来表述新的UI结构。假如每次render都间接利用新的捏造DOM来天生实在DOM结构,那末会带来大量对实在DOM的操纵,影响步伐实行服从。究竟上,React会经过比力两次捏造DOM结构的变化找出不同部分,更新到实在DOM上,从而淘汰终极要在实在DOM上实行的操纵,进步步伐实行服从。这一进程就是React的和谐进程(Reconciliation),其中的关键是比力两个树形结构的Diff算法。
留意在Diff算法中,比力的两方是新的捏造DOM和旧的捏造DOM,而不是捏造DOM和实在DOM,只不外Diff的结果会更新到实在DOM上。一般情况下,比力两个树形结构差此外算法的时候复杂度是O(N^3),这个服从明显是没法担任的。React经过总结DOM的现实利用处景提出了两个在绝大大都理论场景下都建立的假定,基于这两个假定,React实现了在O(N)时候复杂度内完成铃捏造DOM树的比力。这两个假定是:(1)假如两个元素的典范不同,那末它们将天生两棵差此外树。(2)为列表中的元素设备key属性,用key标识对应的元素在屡次render进程中能否发生变化。下面先容在不怜悯况下,React具体是怎样比力两棵树的差此外。React比力两棵树是从树的根节点起头比力的,根节点的典范不同,React实行的操纵也不同。
1.当根节点是不同典范时从div酿成p、从ComponentA酿成ComponentB,大要从ComponentA酿成div,这些都是节点典范发生变化的情况。根节点典范的变化是一个很大的变化,React会以为新的树和旧的树完全不同,不会再继续比力其他属性和子节点,而是把整棵树拆掉重建(包含捏造DOM树和实在DOM树)。这里需要留意,捏造DOM的节点典范分为两类:一类是DOM元素典范,比如div、p等;一类是React组件典范,比如自界说的React组件。在旧的捏造DOM树被撤除的进程中,旧的DOM元素典范的节点会被烧毁,旧的React组件实例的componentWillUnmount会被挪用;在重建的进程中,新的DOM元素会被插入DOM树中,新的组件实例的componentWillMount和componentDidMount方式会被挪用。重建后的新的捏造DOM树又会被团体更新到实在DOM树中。这类情况下,需要大量DOM操纵,更新服从最低。
2.当根节点是类似的DOM元素典范时假如两个根节点是类似典范的DOM元素,React会保存根节点,而比力根节点的属性,然后只更新那些变化了的属性。例如:[插图]React比力这两个元素,发现只要className属性发生了变化,然后只更新捏造DOM树和实在DOM树中对应节点的这一属性。
3.当根节点是类似的组件典范时假如两个根节点是类似典范的组件,对应的组件实例不会被烧毁,只是会实行更新操纵,同步变化的属性到捏造DOM树上,这一进程组件实例的componentWillReceiveProps()和componentWillUpdate()会被挪用。留意,对于组件典范的节点,React是没法间接晓得怎样更新实在DOM树的,需要在组件更新而且render方式实行完成后,按照render返回的捏造DOM结构决议怎样更新实在DOM树。比力完根节点后,React会以一样的原则继续递归比力子节点,每一个子节点相对于其层级以下的节点来说又是一个根节点。如此递归比力,直到比力完两棵树上的全数节点,盘算获得终极的不同,更新到DOM树中。当一个节点有多个子节点时,默许情况下,React只会依照顺序逐一比力两棵树上对应的子节点。例如,比力下面的两个节点,两棵树上的first
和second
子节点会别离被婚配,终极只会插入一个新的节点third
。
但假如在子节点的起头位置新增一个节点,情况就会变得截然不同。例以下面的例子,third
插入子节点的第一个位置,React会把第一棵树的
first
和第二棵树的third
举行比力,把第一棵树的second
和第二棵树的first
举行比力,末端发现新增了一个second
节点。这类比力方式会致使每一个节点都被点窜。[插图]为了处理这类低效的更新方式,React供给了一个key属性。在2.4节已经先容过,当衬着列表元素时,需要为每一个元素界说一个key。这个key就是为了帮助React进步Diff算法的服从。当一组子节点界说了key,React会按照key来婚配子节点,在每次衬着以后,只要子节点的key值没有变化,React就以为这是同一个节点。例如,为前面的例子界说key:
界说key以后,React就能判定出<li key="third">third这个节点是新增节点,first和<li key="second">second两个节点并没有发生改变,只是位置发生了变化而已。如此一来,React只需要实行一次插入新节点的操纵。这里同时揭露了另一个题目,尽管不要利用元素在列表中的索引值作为key,由于列表中的元素顺序一旦发生改变,就大要致使大量的key生效,进而引发大量的点窜操纵。例如,下面的写法应当尽管束止:[插图]末端,需要提醒读者,本章先容的Diff算法是React当前采纳的实现方式,React会不停改良Diff算法,以进步DOM比力和更新的服从。

免责声明:假如加害了您的权益,请联系站长,我们会实时删除侵权内容,感谢合作!
感激您的阅读
回复

使用道具 举报

0条回复
跳转到指定楼层
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Copyright © 2001-2015 忽悠兄 X3.2 © 2001-2013 Comsenz Inc.

Archiver|手机版|小黑屋| Comsenz Inc.  |网站地图

快速回复 返回顶部 返回列表