Diff算法
Vue 和 React 都是基于 vdom 的前端框架,组件渲染会返回 vdom,渲染器再把 vdom 通过增删改的 api 同步到 dom。
当状态发生改变时,react会根据【新的状态】生成【新的虚拟DOM】
然后将新旧虚拟DOM进行 diff比较,比较规则如下:
旧虚拟DOM 中找到了与 新虚拟DOM 相同的 key
若虚拟DOM中的内容没变,则直接使用之前的真实DOM
若虚拟DOM中的内容变了,则生成新的真实DOM并进行替换
旧虚拟DOM 中未找到与 新虚拟DOM 相同的 key,则根据数据创建新的真实DOM,然后渲染到页面
这里对比两棵 vdom 树,找到有差异的部分的算法,就叫做 diff 算法。
key的作用
key用于唯一标识dom,提高渲染性能
1.在列表循环中,react/vue都要求加入一个key值来提升性能。key值为是否重新渲染列表项的唯一标识。如果更新前后key值相同,那么就采用就地复用策略,而不是重新去渲染,大大提高了性能。
2.不添加key,diff算法进行的只是浅层比较,例如在新旧DOM对比时,两处引用的是一样的组件component,但它比较到父节点span与div不同就停止比较了,重新渲染span和div下的所有子节点,这样重复渲染太多,效率极低。
虚拟DOM拥有key的更新逻辑
- 简单的说: key是虚拟DOM对象的标识,在更新显示时key起着极其重要的作用
- 详细的说:当状态中的数据发生变化时,react会根据【新数据】生成新的虚拟DOM
随后React进行了【新虚拟DOM】和【旧虚拟DOM】的比较,比较规则如下:
a:旧虚拟DOM找到了与新虚拟DOM相同的key:
(1).若虚拟DOM中内容没变,直接使用之前的真实DOM
(2).若虚拟DOM中内容变了,则生成新的真实DOM,随后替换页面中之前的真实DOM
b:旧虚拟DOM中未找到与新虚拟DOM相同的key
根据数据创建新的真实DOM随后渲染到页面
用index作为key可能会引发的问题:
- 若对数据进行:逆序添加、逆序删除等破坏顺序的操作:会产生没有必要的真实DOM更新 ===>界面效果没问题 但效率低
- 如果结构中还包含输入类的DOM,会产生错误的DOM更新 ===>界面有问题
- 注意:如果不存在对数据的逆序添加 逆序删除等破坏顺序的操作,仅用于渲染列表展示,使用index作为key是没有问题的。
开发中如何选择key
- 最好每条数据的唯一标识作为key,比如id
- 如果只是简单的展示数据,index也可以