• Vue15 vfor和key的作用及原理


      部分转自https://blog.csdn.net/cun_king/article/details/120714227

    1 v-for指令

    1.1 简介

      用于遍历。

      当在组件中使用 v-for 时,key 现在是必须的。它需要一个唯一id

      

    1.2 遍历数组

    <template>
        <p v-for="(item,index) in list" :key="index">索引{{index}}----{{item}}</p>
    </template>
     
    <script>
     export default {
        data () {
        return {
          list:[1,2,3],
        }
      },
     }
    </script>

     

    1.3 遍历对象数组

    <template>
        <p v-for="(item,index) in list" :key="index">索引{{index}}--{{item.name}}--{{item.money}}</p>
    </template>
     
    <script>
     export default {
        data () {
        return {
          list:[
             { "name": "小米手机", "money": 100 }, 
             { "name": "华为手机", "money": 200 }, 
             { "name": "苹果手机", "money": 300 }, 
             { "name": "魅族手机", "money": 400 }
          ],
        }
      },
     }
    </script>

     

    1.4 遍历对象

    <template>
         <!-- 注意:在遍历对象身上的键值对的时候, 除了 有  val  key  ,在第三个位置还有 一个 索引  -->
        <p v-for="(val, key, i) in list">值是: {{ val }} --- 键是: {{key}} -- 索引: {{i}}</p>
     
    </template>
     
    <script>
     export default {
        data () {
        return {
          list:{
            id: 1,
            name: '小明',
            gender: '男'
          },
        }
      },
     }
    </script>

     

    1.5 遍历字符串

    <body>
    
        <div id="root">
    
         <ul>
            <li v-for="(value,index) of name">
                {{value}}:{{index}}
            </li>
         </ul>
       
        </div>
        
        <script type="text/javascript" >
        
         const vm = new Vue({
          el:'#root',
          data:{
           name:'杭州历史',
           
          }
        })
          
         </script>
        </body>

    2 key属性

    2.1 简介

      key在Vue是DOM对象的标识;
      进行v-for列表展示时,不指定key,默认key是index;
      如果数据只做展示使用,使用index作为key是没有任何问题的;
      如果使用index作为key,而后续操作会破坏顺序,一定会带来效率问题,严重时会渲染出错误的DOM

    2.2 key的作用

      key就是一个标识,被使用在Vue中。再详细一点,key被使用在Vue中的虚拟DOM中,并不会出现在真实DOM中

    2.3 仅展示列表时使用不同的key

    2.3.1 示例1-不设置key

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>key的原理</title>
    
        <!--引入vue-->
        <script type="text/javascript" src="../js/vue.js"></script>
        
    </head>
    <div id="root">
        <h2>人员列表</h2>
        <ul>
            <li v-for="(p,index) in persons">
                {{p.name}}-{{p.age}}
            </li>
        </ul>
    </div>
    <body>
        <script type="text/javascript">
            const vm = new Vue({
                el:'#root',
                data:{
                    persons:[
                        {'id':'001', 'name':'张三','age':'18'},
                        {'id':'002', 'name':'李四','age':'19'},
                        {'id':'003', 'name':'王五','age':'20'}
                    ]
                }
            })
        </script>
    </body>
    </html>

      上述示例html文件中并没有使用到key,似乎也没有问题。当然,单纯地展示数据,不写key是不会存在问题的。

      

    2.3.2 设置id为key

    <li v-for="(p,index) in persons" :key="p.id">
        {{p.name}}-{{p.age}}
    </li>

      页面展示结果和上图结果一模一样

      而如果我们在浏览器上查看元素,li上面也不会看到key属性的存在

      

    2.3.3 设置index为key

    <li v-for="(p,index) in persons" :key="index">
        {{p.name}}-{{p.age}}
    </li>

      页面效果也是一样的

      截至目前,我们可以得到两个结论:

        

    2.3.4 小结 

      1) 只做数据展示用,不写key是没有任何影响的;

      2)key不会出现在真实DOM中

      3)实际上,即使不写key,Vue在生成真实DOM时,也用到了key,默认是数据索引(index)

    2.4 不仅仅是展示的时候

      在展示人员信息的基础上显示索引,并且添加一个按钮,功能是在头部添加人员信息

    2.4.1 示例 index作为key

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>key的原理</title>
    
        <!--引入vue-->
        <script type="text/javascript" src="../js/vue.js"></script>
        <link rel="icon" href="../favicon.ico" type="image/x-icon" />
    
    </head>
    <div id="root">
        <h2>人员列表</h2>
        <button @click="add">添加一个老刘</button>
        <ul>
            <li v-for="(p,index) in persons" :key="index">
                {{p.name}}-{{p.age}}-{{index}}
            </li>
        </ul>
    </div>
    <body>
        <script type="text/javascript">
            const vm = 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>
    </body>
    </html>

       点击按钮,添加一个新人物,这个时候索引发生了变化,新添加的人物“老刘”变为了索引0。

       也就是说,使用index作为key,那么元素的index是可能会变化的

    2.4.2 示例 index作为key

      不展示索引了,改为输入框,在每个人物后面的输入框内写上人物的姓,观察新插入数据后原始数据的变化

    <li v-for="(p,index) in persons" :key="index">
        {{p.name}}-{{p.age}}
        <input type="text">
    </li>

        在输入框中输入内容,效果如上图所示,似乎没有什么不对,接下来就是见证奇迹的时刻

      添加老刘,出现了问题,和我们预想的不一样。如下图,输入框和姓名对不上了。

      

    2.4.3 id作为key

    如果修改为数据的唯一标识,则不会产生这样的问题
    <li v-for="(p,index) in persons" :key="p.id">
        {{p.name}}-{{p.age}}
        <input type="text">
    </li>

    如下图,添加老刘后,名字和输入框还是对应的

    3 key的原理

      那么为什么使用index作为key会出现上面的问题的,二使用id就不会呢?

    3.1 虚拟dom

      要解释key的实现原理,就要引入Vue一个十分重要的概念——虚拟DOM

      给出一组数据和模板,Vue要把这些数据渲染到页面上,首先要生成虚拟DOM,然后根据虚拟DOM去生成真实的DOM,真实的dom就是页面上显示的。如果数据发生了改变,Vue会生成新的虚拟DOM,然后再去生成新的真实DOM,关键就是这个新的真实DOM的生成方式了。

      并不是直接通过新的虚拟DOM生成新的真实DOM,否则虚拟DOM一点用处也没有了。Vue的操作是,拿新的虚拟DOM与之前的旧的虚拟的DOM去做比较,这个比较通过key来对应的,会把key相同的新旧虚拟DOM进行比较。如果相同,直接延用之前虚拟dom生成的真实dom即可,如果不同,则生成新的真实DOM对象。

    3.2 过程分析

    3.2.1 key为index的情况

      根据数据生成真实DOM的流程如下:(注意,下图的真实DOM中输入框里的内容为生成页面后手动添加)

       然后,添加人物“老刘”,获取到一组新数据

       Vue拿新数据生成新的虚拟DOM,注意,由于老刘放到了数组最前面,所以数组里面的数据的index发生了变化

       在生成真实DOM时,就需要用新生成的虚拟DOM和原来的虚拟DOM作比较(一条一条分析)

     

       对比第一条,key为0,找到旧DOM中key为0的数据,发现“老刘-40”和“张三-18”不同,创建新的真实DOM;再往后,发现输入框一致(注意,比较的是虚拟DOM,输入框里面是没有输入的文字的,所以是一致的),不必重新渲染,直接使用原来真实DOM的内容。第一条内容就出现了,而这个输入框还携带有张三的姓

      对比第二条,key为1,找到旧DOM中key为1的数据,发现“张三-18”和“李四-19”不同,创建新的真实DOM;再往后,发现输入框一致,不必重新渲染,直接使用原来真实DOM的内容。第二条内容就出现了,而这个输入框还携带有李四的姓

      之后同理

      回顾这个过程,key是作为虚拟DOM中对象的唯一标识,标识出了数据的“身份信息”,Vue在虚拟DOM中会根据这个“身份标识”去对比内容,设计的初衷是为了节省资源开支,不必渲染重复的部分。在本示例中,不但带来了效率问题,还渲染出了错误的DOM,后果非常严重

    3.2.2 key为id的情况

      直接进入添加“老刘”后的新旧DOM对比

      

      对比第一条,key为‘004’,发现在旧DOM中并不存在,直接生成新的真实的DOM。

      对比第二条,key为‘001’,发现旧DOM中key为‘001’的数据相同,直接将原来的真实的DOM拿过来使用。

      ……

      最后生成正确的DOM,节省了资源开支

     

  • 相关阅读:
    ios初级必看视频
    Md5加密
    Jmail发送邮件
    NPOI Helper文档
    jquery 序列化
    mvc DropDownList默认选项
    获取HTML
    EntityFramework Reverse POCO Generator工具
    全选反选
    mvc导出EXCEL
  • 原文地址:https://www.cnblogs.com/jthr/p/16435164.html
Copyright © 2020-2023  润新知