key是什么
在vue中,我们经常使用的指令其中必定有key,我们先看看vue的官网文档中是怎么定义key这个指令的
- vue使用的虚拟dom,不直接操作dom元素,在操作虚拟dom的时候又使用了diff算法。diff算法的实现基于两个假设: 两个相同的组件产生类似的DOM结构,不同的组件产生不同的DOM结构。
- 同一层级的一组节点,他们可以通过唯一的id进行区分。基于以上这两点假设,使得虚拟DOM的Diff算法的复杂度从O(n^3)降到了O(n)。
粘一段vue比较是否是相同节点的代码:
function sameVnode (a, b) {
return (
a.key === b.key && (
(
a.tag === b.tag &&
a.isComment === b.isComment &&
isDef(a.data) === isDef(b.data) &&
sameInputType(a, b)
) || (
isTrue(a.isAsyncPlaceholder) &&
a.asyncFactory === b.asyncFactory &&
isUndef(b.asyncFactory.error)
)
)
)
}
从这里可以看到,如果我们给元素一个唯一的key值,在dom发生变化时可以很快速的判断出是否是同一节点,从而判断是否需要重新渲染dom。
如果没有key,C,D,E节点都需要重新渲染 如果每个组件都有key值,那么他会直接比较原组件里的key值是否存在,只需要插入新增的F节点即可,不需要重新渲染CDE节点
为什么v-for不建议使用index做key
使用v-for
更新已渲染的元素列表时,默认用就地复用
策略;列表数据修改的时候,他会根据key值去判断某个值是否修改,如果修改,则重新渲染这一项,否则复用之前的元素。如果用index做key,下标发生改变时可能就会出现一些问题,比如:
<div>
<p v-for="(v,i) in spans" :key="i">
<input type="text"><button @click="del(i)">删除</button>
</p>
</div>
setup () {
let spans = reactive([])
spans.push({ id: 1, value: 1 }, { id: 2, value: 2 }, { id: 3, value: 3 })
let del = (i) => {
console.log(`删除第${i + 1}行`)
spans.splice(i,1)
}
return { spans, del }
}
明明我们删除的是第二行,可是为什么界面上第三行没有了。
- 删除第二行,数据发生了变化,数据变化驱动视图层变化,spans的长度变为2,那么只剩下了key=0和key=1的p节点。原先存在key=1的节点,vue的复用策略会让继续复用前两个节点,render过后页面上的第三行没有了。
- 有时候我们复现不出来,是因为我们组件的props和data的数据关联起来了,第一次render过程和之前一样,但是props值改变又触发了一次render过程,绑定了正确的props,所以看起来时正常的样子。如图中的代码input输入框没有双向绑定,所以没有触发第二次的render。
- 如果子节点是文本节点的话,vue也做了单独处理,直接替换原先的文本节点,所以也不会复现出上面的情况
所以在我们绑定key值的时候建议使用唯一值,比如后端数据接口返回的列表id,或者前端生产一个uuid
结语
写的不好,有错误的地方烦请各位大佬多多指教,感恩家人感恩?
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!