现象描述:添加小王在第一个元素,在li元素可以看出来,但是在后面的输入框小张的位置占用了。因为添加小王在第一个元素,它的key是0,旧的dom的key=0是小张。所以校长被顶上去了。看到这个现象特意去学了react虚拟dom的diff算法。
diif算法虚拟dom的更新过程:
1.旧的虚拟dom的key寻找新的dom相同的key;
2.找到相同的key,内容有变化,就更新该位置的内容
3.找到相同的key,内容没有变化,该位置的内容不变
4.若找不到,则更新真实的dom.
用index作为key,对表格进行增删查改,序号会更新排序,也就是新元素的长度多少,就会更新多少次的真实dom。这样无疑效率变低。
那么,一定用key?不用可以吗?
当不带Key的时候,采用的是遍历的方式来对比新旧节点,从而达到更新节点的效果。组件react不知道某个节点是否移动了。
当索引位置发生变化,元素的类型不同,就要重新销毁树重建,效率太地下。但是,在动态的增删中,列表渲染通常都是相同的类型,触发了列表渲染通常都是相同的类型,所以位置变动时,多半是会触发节点原地复用效果,不会导致树的销毁重建发生。只是有一点:这个节点有自己的内部状态,最经典的莫过于输入框。
原因是 React 做了原地复用,而 input 没有传 props,不需要打 props 补丁,保持了原样
(我原来用index作为key,也会出现这个情况,具体什么原因有待研究)
带key的时候使用的是map映射来更新节点。
在模板简单的时候使用就地复用(就是不使用key)效率会更高。
所以使用key并不意味着一定可以提高diff算法的效率。
key的作用主要是为每个节点设置一个唯一的标识,可以更快,更准确的拿到节点。
在一些情况下,还可以避免就地复用带来的副作用(表单数据错位)
参考文档:https://blog.csdn.net/fe_watermelon/article/details/125550099