React笔记(二) Diff算法及原理、key的作用、虚拟DOM

React笔记(二)
1.虚拟DOM
  • 虚拟DOM即虚拟节点,是React利用JSX将JS的Object对象模拟成一个DOM内真实节点对象,并使用render方法渲染到页面上。在React中文官网Virtual DOM 及内核 – React (reactjs.org)中将其称为一种概念,一种UI会以理想化的,虚拟的表现形式保存于内存之中。数据结构上虚拟DOM与真实DOM相同,均是一棵树。
2.Diff算法
  • 传统的Diff算法,也就是通过一颗树以最小步数构建另一颗树时需要O(n3)的事件复杂度,因为整体可以看作两步,第一步通过动态规划将新树与旧树排列成相同的节点顺序,时间复杂度为O(n2);第二步编辑树时需要递归遍历,因此时间复杂度为O(n)。
  • 但React为了减少页面渲染的时间复杂度,使用了更为先进的Diffing算法。整体流程为以下步骤
    • 当状态内的数据发生变化时,React会根据新数据生成新的虚拟DOM,随后React进行新的虚拟DOM与旧的虚拟DOM树的diff比较
      • 当旧虚拟DOM树中找到了与新虚拟DOM相同key时:
        • 如果虚拟DOM中的内容没有变化,就直接使用之前的真实DOM
        • 如果虚拟DOM中的内容有变化,就生成新的虚拟DOM,随后替换掉页面中的之前的真实DOM
      • 如果旧虚拟DOM树中未找到与新虚拟DOM相同的key:
        • 根据数据创建新的真实DOM,随后渲染到页面上
  • 在启用Diff算法后,系统根据先序深度优先遍历两颗树所比较出来的差异,会作为一个批次传递给UI,UI会根据这一批的更新对真实DOM进行更新,提高性能。
3.Key
  • key在Diff算法中起到了唯一标识的作用,所以建议使用数据的唯一标识符,例如ID等。当出现循环遍历时不建议使用index作为key。因为如果在循环遍历中,存在逆序增加(即从前向后添加数据),逆序删除等破坏原有顺序的操作时,会产生一些没有必要的真实DOM更新。理由如上方Diff算法所示,由于破坏原有顺序,所有index对应的内容都发生了变化,因此导致所有的虚拟DOM都需要生成新的并对页面上的进行替换。并且当其中存在有输出类型的元素时,其也会导致刷新错误。

    class Demo extends Component {
      constructor(props){
        super(props);
      }
      state = {
        people:[
          {name:'小张',id:1},
          {name:'小李',id:2},
        ]
      };
      addPerson = ()=>{
        var prePeople = this.state.people;
        this.setState({people:[{name:'小王',id:3},...prePeople]});
      }
      render() {
        var {people} = this.state;
        return (
          <div>
            {people.map((element,index) => {
              return <div key={index}>{element.name}<input type="checkbox"/> </div>
            })}
            <button onClick={this.addPerson}>点我添加小王</button>
          </div>
        )
      }
    }
    

    在这个例子中使用了index作为key,当在页面选择小张后的checkbox后,点击添加小王,会使得小王的后面的checkbox成为被选中状态,而小张后的checkbox不是选中状态。但是将keyindex替换为element.id就不会出现这个问题了。

参考文章

React虚拟DOM浅析 - 简书 (jianshu.com)

传统Diff算法为什么时间复杂度要O(n ^3) - 掘金 (juejin.cn)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值