vue中 key值作用(附加为什么key值不能为index)

一.key在v-if和v-else中的作用

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <!-- 导包 -->
    <script src="./vue.js"></script>
</head>

<body>

    <!-- HTML结构 -->
    <div id="app">
        <button v-text="'点我更换登入方式'" @click="flag=!flag" ></button>
        <div v-if="flag" v-key="phone">
            手机号:<input type="text" placeholder="请输入手机号">
            <br>
            验证码:<input type="text" placeholder="请输入验证码">
        </div>
        <div v-else>
            邮箱:<input type="text" placeholder="请输入邮箱">
            <br>
            密码:<input type="text" placeholder="请输入邮箱密码">
        </div>
    </div>

    <script>
        var app = new Vue({
            //el:挂载点
            el: '#app',
            //data: 要渲染的数据
            data: {
                flag:true,
            }
        })
    </script>
</body>

</html>

我们先把这行代码的 :key="phone"去掉 然后输入手机号和验证码 当我点击 ‘点我更换按钮时’ 我们会神奇的发现,上次输入的值依然存在与input表单框中
这是为什么呢?

这是因为vue中存在diff算法的原因 算法原理我已经在上一个篇章中进行了简单的梳理
deff算法会将新的 虚拟DOM 和旧的 虚拟DOM 进行对比 找出差异 将差异封装为补丁 通过方法的循环遍历然后打到 真实DOM 上,以差异化最小的代价去操作DOM 无差异的地方将会得到复用
当我还未点击’更换按钮’时,此时

 <div v-if="flag" v-key="phone">
            手机号:<input type="text" placeholder="请输入手机号">
            <br>
            验证码:<input type="text" placeholder="请输入验证码">
        </div>

会生成一个真实的DOM(也就是渲染到页面的DOM)该真实DOM会在vue中生成一个以JS对象形式的虚拟DOM,我们称他为“旧的虚拟DOM”当我点击‘切换按钮’时

<div v-if="!flag">
            邮箱:<input type="text" placeholder="请输入邮箱">
            <br>
            密码:<input type="text" placeholder="请输入邮箱密码">
        </div>

该模块中有 文本内容 和标签属性值被改变 所以也就形成了新的虚拟DOM 我们称他为“新的虚拟DOM”
新的虚拟DOM和旧的虚拟DOM进行对比 把修改的内容作为补丁 缝到真实的DOM中 (这也就实现了少量的DOM操作渲染一个新的模块效果)
但在新旧虚拟DOM对比时 无论是新的还是旧的虚拟DOM中 标签节点中都没有value这个属性的存在 所以也就在缝补过程中 会复用之前输入的内容
那怎么解决这个这个复用问题呢?
这样也不总是符合实际需求,所以 Vue 为你提供了一种方式来表达“这两个元素是完全独立的,不要复用它们”。只需添加一个具有唯一值的 key attribute 即可

([vue官方语术:Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。因此在上面的代码中点击‘切换’将不会清除用户已经输入的内容。因为两个模板使用了相同的元素, 不会被替换掉——仅仅是替换了它的 placeholder])

二.key在v-for中的作用

我们先看一下这个代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="./vue.js"></script>
</head>
<body>
  <div id="app">
    <p v-for="item in items" :key="item">{{item}}</p>
  </div>
  <script>
    const app=new Vue({
      el:'#app',
      data:{items:['a','b','c','d','e']},
      mounted() {
        setTimeout(()=>{
          this.items.splice(2,0,'f')
        },2000);
      },
        
      
    })
  </script>
</body>
</html>

首先我要说说明一下 :key 后面的值不建议写 下标index 因为在我们还未进行添加操作时 旧的虚拟节点中 如下
key=0 对应是 a
key=1 对应是 b
key=2 对应是 c
key=3 对应是 d
key=4 对应是 e
当我们添加时 对数据修改 此时生成一个新的虚拟节点 如下
key=0 对应是 a
key=1 对应是 b
key=2 对应是f
key=3 对应是 c
key=4 对应是 d
key=5 对应是 e
vue中规定 key是确立一个元素是完全独立的
key=2 对应f元素 和c元素
key=3 对应d元素 和c元素 …
这样会造成 key值混乱 完全违背了vue设置key值的初衷 所以不建议

接下里我们回归正题
继续说key值在v-for中的作用 如果不写key vue会根据diff算法 根据新旧DOM的差异封装补丁 对真实DOM进行打补丁的过程 比如该案例 在我没有写key的情况 在新旧DOM中 b元素 往后的其他元素他们标签他们相同所以默认为是同一个虚拟节点 只有文本不同 所以将文本封装为补丁(最后还多一个p标签 也将这个差异封装为补丁) 打在真实DOM实现页面渲染
注意只看他打节点的部分 此处是。。没加KEY值。。节点操作 直接跳转到 11 :10秒位置 注意c的变化 注意c的变化 注意c的变化 以及下面元素的变化
注意只看他打节点的部分 此处是。。没加KEY值。。节点操作 直接跳转到 11 :10秒 位置 注意c的变化 注意c的变化 注意c的变化 以及下面元素的变化
直接跳转 13:00 看他打节点操作 此处是加了KEY值的操作 注意观察页面渲染
直接跳转 13:00 看他打节点操作 此处是加了KEY值的节点操作

1.我们可以清晰看到 没加key值 相当于对 真实DOM进行了4(反正是多次 不用纠结 0.0)次DOM操作
inne(修改文本内容为f)
inne(修改文本内容c)
inne(修改文本内容d)
创creat(创建)p标签 append(插入)p标签 inne(修改文本内容e)
2.我们可以清晰看到 没加key值 相当于对 真实DOM进行了1(反正是没几次 不用纠结 0.0)次DOM操作
通过key值 明确了要添加补丁 打在真实DOM的位置
创creat(创建)p标签 append(插入)p标签 inne(修改文本内容为f)
总结
1、 key的作用主要是为了高效的更新虛拟DOM,其原理是vue在patch(补丁)过程中通过key可以精准判断两个节点是否是同一个,从而避免频繁更新不同元素,使得整个patch过程更加高效,减少DOM操作量,提高性能。
2、 另外,若不设置key还可能在列表更新时引发一些隐蔽的bug。如某行数据不该更新的却更新了。
3、vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果。

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值