一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情。
我要一步一步往上爬~大家好,今天我们来一起学习一下列表的Key属性。
1.列表使用
列表用<li>标签表示,想生成多个列表,我们可以加上v-for属性,遍历生成多个相同结构的数据,它的语法是v-for="(item, index) in xxx" :key="yyy"
key是标签属性,index是每条数据的索引值,给每个数据打上了唯一标识
<div id="root">
<ul>
<li v-for="(p,index) in persons" :key="index">
{{p.name}}-{{p.age}}
</li>
</ul>
</div>
<script type="text/javascript">
new Vue({
el:'#root',
data:{
persons:[
{id:'001',name:'张三',age:18},//每个人都是一个对象,{}
{id:'002',name:'李四',age:19},
{id:'003',name:'王五',age:20}
],
}
})
</script>
结果展示:
2.v-for可遍历类型
上面的例子我们遍历的是数组,数组里面有三个对象,除此之外,我们还可以遍历对象、字符串和遍历指定次数.,具体视线可以看下面的例子,可以看出index数据索引是从0开始的。
3.Key属性
用下面这个例子来讲解一下key的原理,以及选用的规则。
这段代码要实现的功能很简单,在已有的列表中通过点击按钮插入一行数据,但是这里有一行text文本输入行,结果是会出现数据参差不齐的错误的,this.persons.unshift(p)这句是指把数据放在最前面。
<div id="root">
<button @click.once="add">添加一个人</button>
<ul>
<li v-for="(p,index) of persons" :key="index">
{{p.name}}-{{p.age}}
<input type="text">
</li>
</ul>
</div>
<script type="text/javascript">
new Vue({
el:'#root',
data:{
persons:[
{id:'001',name:'张三',age:18},
{id:'002',name:'李四',age:19},
{id:'003',name:'王五',age:20}
]
},
methods: {
add(){
const p = {id:'004',name:'老刘',age:40}
this.persons.unshift(p)
}
},
})
</script>
文本输入框中18,19,20是我们自己输入的,但是插入数据后,数据就会出现不对应的情况,这是为什么呢?
3.1 原理分析
接住这张图片我们分析一下整个流程:
- 初始数据在代码中给定,根据数据生成虚拟Dom,这上面上存在的Key是为了高效工作的,内存上出现了三个虚拟节点
- 虚拟Dom转为真实Dom,用户在真实DOM上输入数据(这里的张三-18....)
- 点击按钮生成新数据后, 根据新数据生成虚拟Dom
- 在生成真实dom以前,新旧虚拟DOM会依赖key进行虚拟dom的对比算法,上例中key都为0的数据对比,
老刘-30和张三-18是不匹配的,所以不可以复用,key为0的数据行直接拿新的虚拟dom中的老刘-30替换页面中之前的真实DOM,而对比input type这个结构属性是完全一样的,直接复用,就拿来了input框框中的张三-18数据。key=“3”在旧虚拟DOM中没有找到相同key,那就创建新的真实DOM随后渲染到页面上。
而上述例子如果使用id作为key就不会出现数据错乱的问题,因为,新添加的数据id=4而不是0,为什么呢?因为这个自增编号一般是数据库返回给我们的,不用我们去维护,有这样一个唯一的数据编号,虚拟DOM转为真实DOM的时候就能保证不出错了。
3.2 Key的选取
上述的例子可以看出在对对数据进行逆序添加/删除,这样这样破坏数据顺序的操作时,如果有例如text的输入DOM时,就会产生问题。而且效率很低,不能复用原来DOM中的数据。
我们选择key的时候需要注意:
- 最好使用每条数据的唯一标识:比如id编号、手机号、学号、身份证号等唯一值
- 如果不破坏数据的顺序,那么使用
index作为key是没问题的