checkbox选中和不选中_你该不会还不知道vfor中 key的作用和原理吧?

v-for中的key

说到这个问题想必要举个例子了

0e5f09a12c669367235ee25d7971655f.png

image

没有key

 <div id="app">    <div>      <input type="text" v-model="name">      <button @click="add">添加button>    div>    <ul>      <li v-for="(item, i) in list">        <input type="checkbox"> {{item.name}}      li>    ul><script>    // 创建 Vue 实例,得到 ViewModel    var vm = new Vue({      el: '#app',      data: {        name: '',        newId: 3,        list: [          { id: 1, name: '李斯' },          { id: 2, name: '吕不韦' },          { id: 3, name: '嬴政' }        ]      },      methods: {        add() {         //注意这里是unshift          this.list.unshift({ id: ++this.newId, name: this.name })          this.name = ''        }      }    });script>  div>

当选中吕不为时,添加楠楠后选中的确是李斯,并不是我们想要的结果,我们想要的是当添加楠楠后,一种选中的是吕不为

ca81d111f5fddd440e683513f5522335.png

38e83a22268ae5929552420dfaf1eeea.png

有key

  
<div id="app">    <div>      <input type="text" v-model="name">      <button @click="add">添加button>    div>    <ul>      <li v-for="(item, i) in list" :key="item.id">        <input type="checkbox"> {{item.name}}      li>    ul><script>    // 创建 Vue 实例,得到 ViewModel    var vm = new Vue({      el: '#app',      data: {        name: '',        newId: 3,        list: [          { id: 1, name: '李斯' },          { id: 2, name: '吕不韦' },          { id: 3, name: '嬴政' }        ]      },      methods: {        add() {         //注意这里是unshift          this.list.unshift({ id: ++this.newId, name: this.name })          this.name = ''        }      }    });script>  div>

同样当选中吕不为时,添加楠楠后依旧选中的是吕不为。

ca81d111f5fddd440e683513f5522335.png

ef1262cc49ab5257d60b0d6c507d9b5b.png

可以简单的这样理解:加了key(一定要具有唯一性) id的checkbox跟内容进行了一个关联。是我们想达到的效果

查过相关文档,图例说明很清晰。

vue和react的虚拟DOM的Diff算法大致相同,其核心是基于两个简单的假设
首先讲一下diff算法的处理方法,对操作前后的dom树同一层的节点进行对比,一层一层对比,如下图:

9464d34c33c757dec7475241049c1f8b.png

before.png

当某一层有很多相同的节点时,也就是列表节点时,Diff算法的更新过程默认情况下也是遵循以上原则。
比如一下这个情况:

df41ac7a981a174e8c11d8869ce772f2.png

我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的:

aab1db224a74b6ceb30761355e07b7a4.png


即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很没有效率?

所以我们需要使用key来给每个节点做一个唯一标识,Diff算法就可以正确的识别此节点,找到正确的位置区插入新的节点。

345de3ff3b5b74a8dcc26639e856a4fa.png

vue中列表循环需加:key="唯一标识" 唯一标识可以是item里面id index等,因为vue组件高度复用增加Key可以标识组件的唯一性,为了更好地区别各个组件 key的作用主要是为了高效的更新虚拟DOM

使用v-for更新已渲染的元素列表时,默认用就地复用策略;列表数据修改的时候,他会根据key值去判断某个值是否修改,如果修改,则重新渲染这一项,否则复用之前的元素;
我们在使用的使用经常会使用index(即数组的下标)来作为key,但其实这是不推荐的一种使用方法;

举个?

const list = [
{
id: 1,
name: 'test1',
},
{
id: 2,
name: 'test2',
},
{
id: 3,
name: 'test3',
},
]
for="(item, index) in list" :key="index" >{{item.name}}</div>

上面这种是我们做项目中常用到的一种场景,因为不加key,vue现在直接报错,所以我使用index作为key;下面列举两种常见的数据更新情况

1.在最后一条数据后再加一条数据

const list = [
{
id: 1,
name: 'test1',
},
{
id: 2,
name: 'test2',
},
{
id: 3,
name: 'test3',
},
{
id: 4,
name: '我是在最后添加的一条数据',
},
]

此时前三条数据直接复用之前的,新渲染最后一条数据,此时用index作为key,没有任何问题;

2.在中间插入一条数据

const list = [
{
id: 1,
name: 'test1',
},
{
id: 4,
name: '我是插队的那条数据',
}
{
id: 2,
name: 'test2',
},
{
id: 3,
name: 'test3',
},
]

此时更新渲染数据,通过index定义的key去进行前后数据的对比,发现

74c4564d1fc80eae9792c3b5c36f1184.png

通过上面清晰的对比,发现除了第一个数据可以复用之前的之外,另外三条数据都需要重新渲染;

是不是很惊奇,我明明只是插入了一条数据,怎么三条数据都要重新渲染?而我想要的只是新增的那一条数据新渲染出来就行了

最好的办法是使用数组中不会变化的那一项作为key值,对应到项目中,即每条数据都有一个唯一的id,来标识这条数据的唯一性;使用id作为key值,我们再来对比一下向中间插入一条数据,此时会怎么去渲染

e056de96f2001511d5c6dedad1eb4371.png

现在对比发现只有一条数据变化了,就是id为4的那条数据,因此只要新渲染这一条数据就可以了,其他都是就复用之前的;

同理在react中使用map渲染列表时,也是必须加key,且推荐做法也是使用id,也是这个原因;

所以一句话,key的作用主要是为了高效的更新虚拟DOM。另外vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果。

72e92d51ae54882ae189f9802614e2f2.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值