diff算法

绪论

相信在面试前端岗位的小伙伴肯定遇到过问关于 diff算法。其实很简单,vuereactdiff算法的比对过程都是差不到的。话不多说,直接开干。

比对过程

将新的虚拟dom与旧的虚拟dom一个个对比;
如果对比的新虚拟dom与旧的虚拟dom的key不相同时,会创建一个新的真实dom进来;
如果对比的新虚拟dom与旧的有相同的key值时,会再对两个虚拟dom进一步比对,有结构或内容相同的地方会进行一个真实dom的复用,不同的地方会替换或者创建。

key值的重要性

使用正确key的优点: 完美的遵循了diff算法,使得多数dom得到复用,减少了不必要的dom更新。
不使用正确的key会造成的问题:造成多处不必要的dom更新,如果存在表单时,可能还会导致界面问题。

示例说明

错误使用key值带来的问题以react为例:

import {PureComponent} from 'react'

export default class App extends PureComponent {
   
    state={
      list:[
        {id:'a',name:'a'},
        {id:'b',name:'b'},
        {id:'c',name:'c'},
      ]
    }
 
    add=()=>{
      this.setState({list:[{id:'d',name:'d'},...this.state.list]})
    }
 
   render() {
     
     return (
       <div className="App">
       <ul >
        {
          this.state.list.map((v,i)=>{
            //当使用 索引 作为key时,造成界面问题
            return <li key={i} style={{margin:'10px'}}>
                     {v.name}<input type="text" />
                   </li>  
            
            //使用 id 就解决了这个问题
            // return <li key={v.id} style={{margin:'10px'}}>
            //          {v.name}:<input type="text" />
            //        </li>   
          })
        }
       </ul>
       <button onClick={this.add}>打乱顺序添加一个人</button>
      </div>
     )
   }
 }

运行结果:
在这里插入图片描述现在在每个输入框输入内容:
在这里插入图片描述
下面看使用不同key值的差别

1.使用索引作为key值,点击按钮后:
在这里插入图片描述可以看到,a输入框 的内容跑到d输入框中了,这显然不是我们想要的结果。有些小伙伴可能会疑惑,为什么会这样呢,下面我就用上面说的diff算法的比对过程来解释这种现象:当我们点击按钮在列表的前面插入了一个item后,使得组件重新渲染,由于这里是列表渲染,react底层会使用diff算法来比对。首先比对第一项,发现key值相同,然后比对这一项新旧virtual dom的结构和内容,相同的地方复用,不同的地方替换或新增,对比后发现表单前面的文字不一样,就使用d:替换了a:,再对比到表单,发现一样直接复用。这里可能有小伙伴疑惑为什么表单是一样的?里面的内容不是不一样吗?这里确实带有点迷惑,不过也很好解释,因为对比的是virtual dom,而用户在表单输入的内容是不会呈现在virtual dom中,可能是因为virtual dom记录的是html prop 而不是dom prop,因此此处对比是一样的。这种复用也就造成了界面的问题。其他item的比对过程以此类推。

2.使用 id作为key值,点击按钮后:
在这里插入图片描述可以看到.使用 id作为key值是没有问题的。现在我使用上面说的diff算法的比对过程来说说这里的比对过程。首先对比第一项的key值,发现不同,直接创建新的dom进来,再对比后面的发现key值都一样,直接全都复用。

总结

可以发现正确的使用key值不仅可以避免出现界面的问题,还减少了react内部的比对步骤,还提高了dom复用性。

结尾

相信看完本篇文章底层小伙伴会发现diff算法也就这么回事。感谢大家阅读本篇文章,如果有问题欢迎提出和分享。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值