likes
comments
collection
share

列表渲染

作者站长头像
站长
· 阅读数 15

v-for

通过 v-for 指令渲染元素。v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是数据源,而 item 则是被迭代的元素别名。

遍历数组:

遍历时可以拿到两个值,一个是 item 迭代项,index 索引。

<template>
  <div>
    <ul>
      <li v-for="(item, index) in ['1', '2', '3']" :key="index">
        {{ item }}
      </li>
    </ul>
  </div>
</template>

使用 of 代替 in 作为分隔符,of 更接近 JavaScript 迭代数组的语法。

<template>
  <div>
    <ul>
      <li v-for="(item, index) of ['1', '2', '3']" :key="index">
        {{ item }}
      </li>
    </ul>
  </div>
</template>

遍历对象:

遍历时可以拿到三个值 (value, key, index)value 属性值,key 属性名,index 索引。

注意:遍历对象的顺序是按属性最早创建的时间排序来。

<template>
  <div>
    <ul>
      <li v-for="(value, key, index) in { name: '张三', gender: '男'  }" :key="key">
        {{ value }} - {{ key }} - {{ index }}
      </li>
    </ul>
  </div>
</template>

key 的作用

在 Vue 中,key 是用来标识每个节点的唯一性,Vue 采用 diff 比较 新/旧 vnode 时,通过 key 来判断两个节点是否相同,从而决定是否需要重新渲染。

不设置 key 值:

在这种下面例子中,通过 v-for 指令渲染的 li 标签并没有设置 key 值。

<template>
  <div>
    <ul>
      <li v-for="(item, index) in list">
        {{ item }}
      </li>
    </ul>
    <button @click="add">新增</button>
    <button @click="del">删除</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      list: ["3", "2", "1"],
      count: 3
    };
  },
  methods: {
    add() {
      // 往数组前面添加数据。
      this.list.unshift(++this.count);
    },
    del() {
      // 删除数组的第一项数据。
      this.list.splice(0, 1);
    }
  },
};
</script>

例子中点击 新增删除 按钮操作的都是列表数据的第一项数据。

按道理在我每次点击 新增删除 就只会在列表的第一项添加一个 li 标签。

但实际上因为没有给 li 设置 key 值作为唯一标识性,在列表数据发生改变时,会产生 新的vnode,Vue 通过 diff新/旧vnode 进行比较,Vue 就会复用已有的元素,只对内容做更新。

最后会发现,在操作时理应只对一条数据做相应的处理,但实际上每次列表数据更新,所有的 li 也会更新,并且新增 或 删除 操作的都是最后一条数据。

使用 index 作为 key 和不设置 key 值一样,index 会随着数组变化而变化。

在操作 动态元素 的情况下,需要保证 key 的不变性。

可以打开 F12,选中 li 的结构后,点击 新增删除 按钮,可以看到所有的 li 元素都发生了 闪烁,是因为 li 元素都发生了更新。

设置 key 值:

<li v-for="(item, index) in list" :key="item">
   {{ item }}
</li>

设置了 key 后,打开 F12,再次操作数据,会发现只有对应的 li 标签发生了更新。

数组更新检测

Vue 对部分的数组方法进行了封装,使用封装后的方法对数组进行操作会触发响应系统,从而触发视图更新。

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

例如,你要在数组最后一项添加内容:

<template>
  <div>
    {{ list }}
  </div>
</template>

<script>
export default {
  data() {
    return {
      list: ["3", "2", "1"],
    };
  },
  mounted() {
    const length = this.list.length;
    this.list[length - 1] = "4";
  },
};
</script>

this.list[length - 1] = 值 这种方式操作数据不会引起页面的刷新。需要使用 Vue 封装过的数组方法。

mounted() { 
    this.list.push("4"); 
},