5

零基础入门Vue之影分身之术——列表渲染&渲染原理浅析 - StarVik

 7 months ago
source link: https://www.cnblogs.com/Star-Vik/p/18008874
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

听我说#

条件渲染 那一篇,我学习到了如何用Vue对dom节点根据条件显示

但单单有条件还不够啊,有时候数据是一大坨一大坨的数据,如果Vue不提供咱要么使用“v-html” 要么就没办法实现

v-html又感觉太low了,Vue提供了另外的指令更好的实现,那便是:列表渲染

列表渲染:v-for#

简单的列表渲染可以使用v-for来完成,而Vue提供了两种采用形式的列表渲染

列表渲染之数组#

假设我有一个数组,然后我希望数组里面的数据,通过展示在ul的一个一个li里面,并且要求数组更新的同时li会自动的增减

假设data如下

//假设下面是Vue的配置对象
{
  data:{
    msgList:[
      {
        name:"张三",
        age:19,
        sex:"男"
      },
      {
        name:"李四",
        age:22,
        sex:"男"
      },
      {
        name:"王五",
        age:20,
        sex:"女"
      },
      {
        name:"陈真",
        age:30,
        sex:"男"
      },
    ]
  }
}

那么dom节点可以这么写,达到渲染的效果

<!--假设这是根节点的内容-->
<ul>
  <li v-for="item of msgList">
    {{item.name}} - {{item.age}} - {{item.sex}}
  </li>
</ul>

此时,ul里面的li渲染出的个数等同于msgList的个数,同时item表示当前li的数组元素

可以用JavaScript的for-of循环来理解,这里用v-for="item in msgList"也是一样的效果

item都是表示msgList的成员

完整代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="./vue.js"></script>
    <title>Document</title>
</head>
<body>
    <div id="root">
        <ul>
            <li v-for="item of msgList">
              {{item.name}} - {{item.age}} - {{item.sex}}
            </li>
        </ul>
    </div>
</body>
<script>
    let vm = new Vue({
        el:"#root",
        data:{
            msgList:[{
                name:"张三",
                age:19,
                sex:"男"
            },
            {
                name:"李四",
                age:22,
                sex:"男"
            },
            {
                name:"王五",
                age:20,
                sex:"女"
            },
            {
                name:"陈真",
                age:30,
                sex:"男"
            }]
        }
    })
</script>
</html>

列表渲染之对象#

Vue还允许配置为对象这种可遍历的变量来使用v-for

如果配置为对象的话,那么会拿到两个参数,一个是key一个是value(先拿到value在拿到key

具体代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="./vue.js"></script>
    <title>Document</title>
</head>
<body>
    <div id="root">
        <ul>
            <li v-for="(value,key) of msgObj">
              {{key}} - {{value}}
            </li>
        </ul>
    </div>
</body>
<script>
    let vm = new Vue({
        el:"#root",
        data:{
            msgObj:{
                name:"陈真",
                age:30,
                sex:"男"
            }
        }
    })
</script>
</html>

当然也可以写一个参数,只接受value

<div id="root">
    <ul>
        <li v-for="value of msgObj">
          {{value}}
        </li>
    </ul>
</div>

完全写法#

无论是对象还是数组,列表渲染都会给当前值索引,所以对于数组的话就可以写成两个参数,显示value后是索引

<ul>
    <li v-for="(item,index) of msgList">
      {{index}}、{{item.name}} - {{item.age}} - {{item.sex}}
    </li>
</ul>

如何使对象的话就这么写

<ul>
    <li v-for="(value,key,index) of msgObj">
      {{index}}、{{key}} = {{value}}
    </li>
</ul>

key的应用&渲染原理浅析#

为了避免出错,无论是react还是vue使用v-for,原则上都应该配置唯一标识作为key

当出现要对数据修改时,未配置唯一标识key可能会出现bug

因此对于需要用上v-for的节点请配置上数据唯一标识作为key

详细解释请参照:维护状态

浅析出错原因#

Vue在监控到数据改变时,并不会如我们所想的一样马上渲染dom

而是会先渲染虚拟dom,然后通过特定算法或者说特定规则去渲染实际dom

渲染规则如下:

  • 当遇到v-for时,首先寻找数据老的虚拟dom和新的虚拟dom的唯一标识进行对比(以li为例)
  • 在li节点中,如果有一样的部分那么照搬老的dom,不重新渲染,直接搬运反之根据新的虚拟dom重新渲染
  • 如果li中这个节点在旧虚拟dom不存在,那么久会按照新的虚拟dom重新渲染

不放图片说不清楚,放图片说一大堆,搬出尚硅谷的视频吧:零基础入门Vue之key的作用和原理

key的具体用法#

key 的特殊 attribute 主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。而使用 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。

对于 Vue中的key 的用法也很简单,他是为了标识v-for每个循环元素的唯一性,所以key也应该是唯一的

<dom v-for="item in list" :key="item.id"></dom>

此时,当前dom与数据唯一的id互相绑定,这样如果dom更新了,新旧虚拟dom就能一一对应的去对比

就不会出现元素紊乱,并且渲染效率低下的问题

具体代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="./vue.js"></script>
    <title>Document</title>
</head>
<body>
    <div id="root">
        <ul>
            <li v-for="item of msgList" :key="item.id">
              {{item.name}} - {{item.age}} - {{item.sex}}
            </li>
        </ul>
    </div>
</body>
<script>
    let vm = new Vue({
        el:"#root",
        data:{
            msgList:[{
                id:1,
                name:"张三",
                age:19,
                sex:"男"
            },
            {
                id:2,
                name:"李四",
                age:22,
                sex:"男"
            },
            {
                id:3,
                name:"王五",
                age:20,
                sex:"女"
            },
            {
                id:4,
                name:"陈真",
                age:30,
                sex:"男"
            }]
        }
    })
</script>
</html>

注:切忌把索引作为key,因为只要不是往末尾插入数据或者删除数据的方式来修改数据,都会造成index失去唯一标识的作用

The End#


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK