html
const list = ref([
{
id:1,
text:"aaa"
},{
id:2,
text:"bbb"
},{
id:3,
text:"ccc"
}
])
html
<ul> <li v-for="(item, index) in list" >{{ item.text }}</li> </ul>
以上代码运行后,渲染出来是这样的:
然后我们给list的末尾加一个新元素:
php
list.value.push({ id:100, text:"ddd" })
加上新元素后,页面展示如下
其实一开始,是有一个虚拟dom列表的,list增加新元素后,又会生成一个新的虚拟dom列表
新旧虚拟dom列表如下,左边的旧的,右边是新的
创建新虚拟dom列表后,与旧的虚拟dom比较,上图种,左边第0个与右边第0个是一样的,所以真实dom里的第0个li不变,
左边第1个与右边第1个是一样的,所以真实dom里的第1个li不变,
左边第2个与右边第2个是一样的,所以真实dom里的第2个li不变
右边有第三个,左边没有第三个,所以会在真实dom列表里新创建一个dom,里面显示ddd
接下来,看看另一种案例:
php
const list = ref([ { id:1, text:"aaa" },{ id:2, text:"bbb" },{ id:3, text:"ccc" }])
xml
<ul> <li v-for="(item, index) in list" >{{ item.text }}</li> </ul>
运行后页面如下:
然后,我们在list的index为1的位置插入一个新元素
php
list.value.splice(1, 0 ,{ id:100, text:"ddd" })
然后页面显示如下:
往list里插入新元素后,新旧虚拟dom列表可以表示如下
然后vue会比较新旧列表
左边第0个与右边第0个是一样的,所以真实dom里的第0个li不变,
左边第1个与右边第1个不一样,所以真实dom里的第1个li会被修改,
左边第2个与右边第2个不一样,所以真实dom里的第2个li会被修改,
右边有第三个,左边没有第三个,所以会在真实dom列表里新创建一个dom,里面显示ccc
我们可以看到,往list里插入新元素后,真实dom里的第1个到第二个li都更新了,这样性能太差了
接下来,再写一个案例,给v-for加key
php
const list = ref([ { id:1, text:"aaa" },{ id:2, text:"bbb" },{ id:3, text:"ccc" }])
css
<ul> <li v-for="(item, index) in list" :key="item.id" >{{ item.text }}</li> </ul>
注意,这里我给li加了个key属性,值为item.id
运行后页面是这样的:
然后,我们在list的index为1的位置插入一个新元素
php
list.value.splice(1, 0 ,{ id:100, text:"ddd" })
然后页面显示如下:
新虚拟dom列表和旧虚拟dom列表可以表示如下:
这次,他们是有key属性的,在有key属性的情况下,新旧虚拟dom的比较过程是这样的:
key为0的旧虚拟dom和key为0的新虚拟dom一样,
key为1的旧虚拟dom和key为1的新虚拟dom一样,
key为2的旧虚拟dom和key为2的新虚拟dom一样
所以真实dom里的这三个li不会改变
新的虚拟dom列表里多了一个key为100的虚拟dom,并且在索引为1的位置
所以vue会在真实的dom里,索引为1的地方插入一个新的li,li里的内容是ddd
看到没,这次不像上一个案例里那样改变了2个li,这次只要增加一个li,原来的三个li完全不用改变,性能是不是比较好了
用index作为key
接下来,说说如果用index来作为key,会怎么样
php
const list = ref([ { id:1, text:"aaa" },{ id:2, text:"bbb" },{ id:3, text:"ccc" }])
css
<ul> <li v-for="(item, index) in list" :key="index" >{{ item.text }}</li> </ul>
运行后页面是这样的:
然后,我们在list的index为1的位置插入一个新元素
php
list.value.splice(1, 0 ,{ id:100, text:"ddd" })
然后页面显示如下:
新虚拟dom列表和旧虚拟dom列表可以表示如下:
他们是有key属性的,在有key属性的情况下,新旧虚拟dom的比较过程是这样的:
key为0的旧虚拟dom和key为0的新虚拟dom一样,所以真实dom里的第0个li不用改变
key为1的旧虚拟dom和key为1的新虚拟dom不一样,所以真实dom里的第1个li要改变
key为2的旧虚拟dom和key为2的新虚拟dom不一样,所以真实dom里的第2个li要改变
新的虚拟dom列表末尾多了一个key为3的虚拟dom,所以在真实li列表末尾创建一个新的li
你看,这样bbb和ccc这两个li都需要被改变,跟上一个案例比较一下,这次改变的真实dom比较多,所以不能用index来作为key的值