网站开发的实践报告,手机网站的做,导购网站怎么做,seo5“在 Vue 中#xff0c;我们在使用 v-for 渲染列表的时候#xff0c;为什么要绑定一个 key#xff1f;能不能用 index 做 key#xff1f;”
在聊这个问题之前我们还得需要知道 Vue 是如何操作 DOM 结构的。
虚拟DOM
我们知道#xff0c;Vue 不可以直接操作 DOM 结构我们在使用 v-for 渲染列表的时候为什么要绑定一个 key能不能用 index 做 key”
在聊这个问题之前我们还得需要知道 Vue 是如何操作 DOM 结构的。
虚拟DOM
我们知道Vue 不可以直接操作 DOM 结构而是通过数据驱动、指令等机制来间接操作 DOM 结构。当我们修改模版中的数据时Vue 会触发重新渲染过程调用render函数它会返回一个 虚拟 DOM 树它描述了整个组件模版的结构。
什么是虚拟DOM呢虚拟DOM是一个对象没想到吧...我们来看看Vue是如何将template模板里面的东西交给浏览器来渲染的 举个栗子
templateul classlistli v-foritem in list :keyitem.index classitem{{ item }}/li/ul
/templatescript setup
import { ref } from vue;
const list ref([html, css, js])
/scriptVue 在渲染这个列表时就会调用render函数它会返回一个类似下面这个虚拟 DOM 树。
let VDom {tagName: ul,props: {class: list},chilren: [{tagName: li,props: {class: item},chilren: [html]},{tagName: li,props: {class: item},chilren: [css]},{tagName: li,props: {class: item},chilren: [js]}]
}虚拟 DOM 的每个节点对应于真实 DOM 树中的一个节点。
当我们修改数据时Vue 又会触发重新渲染的过程。
const list ref([html, css, vue]) //修改列表第三项js-vueVue 又会生成一个新的虚拟DOM树
let VDom {tagName: ul,props: {class: list},chilren: [{tagName: li,props: {class: item},chilren: [html]},{tagName: li,props: {class: item},chilren: [css]},{tagName: li,props: {class: item},chilren: [vue]}]
}注意观察这里最后一个节点的子节点为vue发生了数据变化Vue内部又会返回一个新的虚拟 DOM。那么 Vue 是如何将这个变化响应给页面的呢
摆在面前的有两条路
要么重新渲染这个新的虚拟 DOM 要么只新旧虚拟 DOM 之间改变的地方。
显而易见只渲染修改了的地方是不是会更节省性能。
巧了尤雨溪也是这样想的于是便有了“ Diff 算法 ”。
Diff 算法
Vue 将新生成的新虚拟 DOM 与上一次渲染时生成的旧虚拟 DOM 进行比较对比出是哪个虚拟节点更改了找出这个虚拟节点并只更新这个虚拟节点所对应的真实节点而不用更新其他数据没发生改变的节点。
我自己总结了一下Diff算法的过程由于代码过多就不在此展示了 新旧虚拟DOM对比的时候Diff 算法比较只会在同层级进行不会跨层级比较。首先比较两个节点的类型如果类型不同则废弃旧节点并用新节点替代。对于相同类型的节点进一步比较它们的属性。记录属性差异以便生成相应的补丁。如果两个节点相同继续递归比较它们的子节点直到遍历完整个树。如果节点有唯一标识可以通过这些标识来快速定位相同标识的节点。如果节点的相同只是顺序变化不会执行不必要的操作。 面试官为什么不用 index 做 key
平常v-for循环渲染的时候为什么不建议用 index 作为循环项的 key 呢
举个栗子
div idappulli v-foritem in list :keyitem.index{{item}}/li/ulbutton clickadd添加/button
/div
scriptconst { createApp, ref } VuecreateApp({setup() {const list ref([html, css, js]);const add() {list.value.unshift(阳阳羊);}return {list,add}}}).mount(#app)
/script我们发现添加操作导致的整个列表的重新渲染按道理来说Diff 算法会复用后面的三项因为它们只是位置发生了变化内容并没有改变。但是我们回过头来发现我们在前面添加了一项导致后面三项的 index 变化从而导致 key 值发生变化。Diff 算法失效了
那我们可以怎么解决呢其实我们只要使用一个独一无二的值来当做key就行了
div idappulli v-foritem in list :keyitem.id{{item.name}}/li/ulbutton clickadd添加/button
/div
scriptconst { createApp, ref } VuecreateApp({setup() {const list ref([{ name: html, id: 1 }, { name: css, id: 2 }, { name: js, id: 3 }, ]);const add() {list.value.unshift({ name: 阳阳羊, id: 4 });}return {list,add}}}).mount(#app)
/script这样key就是永远不变的更新前后都是一样的并且又由于节点的内容本来就没变所以 Diff 算法完美生效只需将新节点添加到真实 DOM 就行了。 如果后端没有返回 唯一 id 唯一标识都可以的
最后
看到这里希望你已经对Diff 算法有了初步的了解想要深入了解可以自行查看Diff 源码。总的来说Diff 算法是一项关键的技术为构建响应式和高效的用户界面提供了基础。最后祝你面试顺利学习进步