• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Vue key的作用和原理

武飞扬头像
N-A
帮助1

目录

引入

key的作用

Key的取值

不绑定key属性

Key值为index

Key值为数据唯一标识

总结


引入

当你使用过Vue时,必定会对v-for的指令非常熟悉。该指令通常用于遍历数组数据。使用v-for指令时,必定离不开key属性。你是否了解该属性,该属性的作用是什么?取值有什么?分别又有什么区别呢?本文将详细介绍Vue中key的作用与原理!

key的作用

当你为一个列表绑定一个key属性时,该属性会存在于虚拟的DOM中,key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据用户对应修改的新数据,来生成新的虚拟DOM。随后Vue会进行新虚拟DOM与旧虚拟DOM的差异比较。进行比较的过程可以分成两种情况:

当旧虚拟DOM中找到了与新虚拟DOM相同的key时,若虚拟DOM中内容没变, 直接使用之前的真实DOM!若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。

当旧虚拟DOM中未找到与新虚拟DOM相同的key时,创建新的真实DOM,随后渲染到到页面。

是不是有点懵,别着急,在下面的例子中会有详细地举例!!

Key的取值

key主要有以下的三种情况,现在我们举一个小案例来分别采用如下的方式,看看具体都有什么效果以及区别是什么。

我们在页面是渲染一个人员的列表,并添加一个按钮,当点击按钮时,会在人员列表前再添加一个新成员。(为啥要在列表前,这是一个关键的点!)

不绑定key属性

当我们在编写v-for时没有添加key属性时,并没有影响到我们想要的效果。对应的实现代码以及效果图如下:

  1.  
    <!DOCTYPE html>
  2.  
    <html>
  3.  
    <head>
  4.  
    <meta charset="UTF-8" />
  5.  
    <title>key的原理</title>
  6.  
    <script type="text/javascript" src="../js/vue.js"></script>
  7.  
    </head>
  8.  
    <body>
  9.  
    <!-- 准备好一个容器-->
  10.  
    <div id="root">
  11.  
    <h2>人员列表</h2>
  12.  
    <button @click.once="add">添加一个老刘</button>
  13.  
    <ul>
  14.  
    <li v-for="p of persons">
  15.  
    {{p.name}}-{{p.age}}
  16.  
    </li>
  17.  
    </ul>
  18.  
    </div>
  19.  
  20.  
    <script type="text/javascript">
  21.  
    new Vue({
  22.  
    el:'#root',
  23.  
    data:{
  24.  
    persons:[
  25.  
    {id:'001',name:'张三',age:18},
  26.  
    {id:'002',name:'李四',age:19},
  27.  
    {id:'003',name:'王五',age:20}
  28.  
    ]
  29.  
    },
  30.  
    methods: {
  31.  
    add(){
  32.  
    const p = {id:'004',name:'老刘',age:40}
  33.  
    this.persons.unshift(p)
  34.  
    }
  35.  
    },
  36.  
    })
  37.  
    </script>
  38.  
    </html>

学新通

这时候可能会有同学会问,不写key属性不也能够正常地显示我们想要的效果吗?所以为何那么麻烦,多加一个key属性!其实,当你没有添加key属性时,系统会默认将绑定的key属性的值指向index。则会列表的索引,例如:{id:'001',name:'张三',age:18}的index值就为0,{id:'002',name:'李四',age:19}的index值就为1,依次类推。来为每一个li标签做标识。

Key值为index

当我们添加key属性,并将该属性的值指向为index时,具体它实现出来的效果就如上的没有添加key属性一样。但是具体的实现代码有一点小区别:

  1.  
    <!DOCTYPE html>
  2.  
    <html>
  3.  
    <head>
  4.  
    <meta charset="UTF-8" />
  5.  
    <title>key的原理</title>
  6.  
    <script type="text/javascript" src="../js/vue.js"></script>
  7.  
    </head>
  8.  
    <body>
  9.  
    <!-- 准备好一个容器-->
  10.  
    <div id="root">
  11.  
    <h2>人员列表</h2>
  12.  
    <button @click.once="add">添加一个老刘</button>
  13.  
    <ul>
  14.  
                   <!-- 绑定了key属性,并将其值指向于index -->
  15.  
    <li v-for="(p,index) of persons" :key="index">
  16.  
    {{p.name}}-{{p.age}}
  17.  
    </li>
  18.  
    </ul>
  19.  
    </div>
  20.  
  21.  
    <script type="text/javascript">
  22.  
    Vue.config.productionTip = false
  23.  
    new Vue({
  24.  
    el:'#root',
  25.  
    data:{
  26.  
    persons:[
  27.  
    {id:'001',name:'张三',age:18},
  28.  
    {id:'002',name:'李四',age:19},
  29.  
    {id:'003',name:'王五',age:20}
  30.  
    ]
  31.  
    },
  32.  
    methods: {
  33.  
    add(){
  34.  
    const p = {id:'004',name:'老刘',age:40}
  35.  
    this.persons.unshift(p)
  36.  
    }
  37.  
    },
  38.  
    })
  39.  
    </script>
  40.  
    </html>

对应的实现和上面的相同,也是能够正确地将效果显示出来。这种写法也是比较常见的。这并没有看出什么问题。但是倘若现在我在每一个列表的后面添加一个输入框,会出现什么样的效果呢?

  1.  
    <div id="root">
  2.  
    <h2>人员列表</h2>
  3.  
    <button @click.once="add">添加一个老刘</button>
  4.  
    <ul>
  5.  
                   <!-- 绑定了key属性,并将其值指向于index -->
  6.  
    <li v-for="(p,index) of persons" :key="index">
  7.  
    {{p.name}}-{{p.age}}
  8.  
                       <!-- 增加了input输入框 -->
  9.  
                       <input type="text">
  10.  
    </li>
  11.  
    </ul>
  12.  
    </div>

学新通

通过以上的效果图我们可以很明显地看出了其出现的问题,但输入框中没有内容时,添加之后并没有什么问题。但是当我们在添加之前先将对应的内容输入到相应的输入框中后,我们会发现添加之后出现了问题。所以为何会出现这种问题呢?我们来看看下面的图形演示:

学新通

当我们把index作为key时,初始数据之后会根据数据生成虚拟的DOM,对应的li标签中的key值分别是0,1,2。当数据生成初始虚拟DOM之后,会创建新的真实DOM,随后渲染到到页面。

而当我们再添加一条数据时,会根据我们新的数据来生成新的虚拟DOM。新的虚拟DOM会与初始的也就是旧的虚拟DOM来进行对比,先找到对应相同的key值的li,若虚拟DOM中内容没变, 直接使用之前的真实DOM,若虚拟DOM中内容变了, 则生成新的真实DOM,对比发现key="0"中的内容有变化,从“张三-18”变成了“老刘-30”,随后替换掉页面中之前的真实DOM。而<input type="text">对比的结果是相同的,因此保存原本的内容。key="1"以及key="2"以此类推。而key="3"并没有在旧虚拟DOM中找到,因此创建新的真实DOM,随后渲染到到页面。

这下明白了吧!!

Key值为数据唯一标识

当我们把key属性的值赋为数据中的唯一标识时,又会出现怎么样的结果呢?我们将persons中的id值赋给key属性。具体代码如下:

  1.  
    <!DOCTYPE html>
  2.  
    <html>
  3.  
    <head>
  4.  
    <meta charset="UTF-8" />
  5.  
    <title>key的原理</title>
  6.  
    <script type="text/javascript" src="../js/vue.js"></script>
  7.  
    </head>
  8.  
    <body>
  9.  
    <!-- 准备好一个容器-->
  10.  
    <div id="root">
  11.  
    <h2>人员列表</h2>
  12.  
    <button @click.once="add">添加一个老刘</button>
  13.  
    <ul>
  14.  
                   <!-- 绑定了key属性,并将其值指向于p.id -->
  15.  
    <li v-for="(p,index) of persons" :key="p.id">
  16.  
    {{p.name}}-{{p.age}}
  17.  
                       <!-- 增加了input输入框 -->
  18.  
                       <input type="text">
  19.  
    </li>
  20.  
    </ul>
  21.  
    </div>
  22.  
  23.  
    <script type="text/javascript">
  24.  
    new Vue({
  25.  
    el:'#root',
  26.  
    data:{
  27.  
    persons:[
  28.  
    {id:'001',name:'张三',age:18},
  29.  
    {id:'002',name:'李四',age:19},
  30.  
    {id:'003',name:'王五',age:20}
  31.  
    ]
  32.  
    },
  33.  
    methods: {
  34.  
    add(){
  35.  
    const p = {id:'004',name:'老刘',age:40}
  36.  
    this.persons.unshift(p)
  37.  
    }
  38.  
    },
  39.  
    })
  40.  
    </script>
  41.  
    </html>

学新通

 我们可以明显地看出,若我们的key属性绑定的值为数据中的唯一标识时,我们就能够得到我们想要的结果。对应的原理图如下:

学新通

由于每一个li标签中绑定的值为id,因此当添加一个新成员时,其对应的id="004",对应的key值为004,并没有在旧的虚拟DOM中找到,因此添加到真实的DOM中并渲染在页面上。其他的就不在多解释,原理都是相同的。

总结

若使用index作为key需要考虑下载两个问题:

其一,若对数据进行逆序添加、逆序删除等破坏顺序的操作时, 会产生没有必要的真实DOM更新 ,虽然界面效果没问题, 但效率低。其二,如果结构中还包含输入类的DOM,会产生错误DOM更新 ,界面会产生问题。

那么我们在开发的过程中该如何选择key呢?

首先最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,用index作为key是没有问题的。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhggagfa
系列文章
更多 icon
同类精品
更多 icon
继续加载