React(精读官方文档) -高级指引 - 协调(Diffing 算法)

设计动力

  • 在某一时间节点调用 React 的 render() 方法,会创建一棵由 React 元素组成的树。在下一次 state 或 props 更新时,相同的 render() 方法会返回一棵不同的树。React 需要基于这两棵树之间的差别来判断如何有效率的更新 UI 以保证当前 UI 与最新的树保持同步。

Diffing 算法

首先:比较两棵树的根节点

  • 对比不同类型的元素
    • 当根节点为不同类型的元素时,React 会拆卸原有的树并且建立起新的树
      • 例如:当一个元素从< a > 变成 < img >,从 < Article > 变成 < Comment >,或从 < Button > 变成 < div > 都会触发一个完整的重建流程
    • 当拆卸一棵树时,对应的 DOM 节点也会被销毁
      • 执行 componentWillUnmount()
      • 所有跟之前的树所关联的 state 也会被销毁,在根节点以下的组件也会被卸载,它们的状态会被销毁
    • 当建立一棵新的树时,对应的 DOM 节点会被创建以及插入到 DOM 中
      • 执行 componentWillMount() 方法,紧接着 componentDidMount() 方法
      <div>
        <Counter />
      </div>
      
      <span>
        <Counter />
      </span>
      //React 会销毁 Counter 组件并且重新装载一个新的组件
      
  • 比对同一类型的元素
    • 当比对两个相同类型的 React 元素时,React 会保留 DOM 节点,仅比对及更新有改变的属性
          //例如:
          <div className="before" title="stuff" />
          <div className="after" title="stuff" />
         //  通过比对这两个元素,React 知道只需要修改 DOM 元素上的 className 属性
      
           <div style={{color: 'red', fontWeight: 'bold'}} />
           <div style={{color: 'green', fontWeight: 'bold'}} />
           //通过比对这两个元素,React 知道只需要修改 DOM 元素上的 color 样式,无需修改 fontWeight
        ```
      
    • 在处理完当前节点之后,React 继续对子节点进行递归
  • 比对同类型的组件元素
    • 当一个组件更新时,组件实例保持不变,这样 state 在跨越不同的渲染时保持一致。React 将更新该组件实例的 props 以跟最新的元素保持一致,并且调用该实例的 componentWillReceiveProps() 和 componentWillUpdate() 方法
    • 下一步,调用 render() 方法,diff 算法将在之前的结果以及新的结果中进行递归
  • 对子节点进行递归
    • 默认条件下,当递归 DOM 节点的子元素时,React 会同时遍历两个子元素的列表;当产生差异时,生成一个 mutation。
      • 在子元素列表末尾新增元素时,更变开销比较小
  • Keys
    • 当子元素拥有 key 时,React 使用 key 来匹配原有树上的子元素以及最新树上的子元素。
      <ul>
       <li key="2015">Duke</li>
       <li key="2016">Villanova</li>
      </ul>
      
      <ul>
       <li key="2014">Connecticut</li>
       <li key="2015">Duke</li>
       <li key="2016">Villanova</li>
      </ul>
      //  React 知道只有带着 '2014' key 的元素是新元素,带着 '2015' 以及 '2016' key 的元素仅仅移动了
      
    • key 不需要全局唯一,但在列表中需要保持唯一
    • 不建议用数组下标作为key;因为一旦有顺序修改,diff 就会变得慢
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值