Vue.js v-for

🌙
手机阅读
本文目录结构

v-for

  • 预期Array | Object | number | string | Iterable (2.6 新增)

用法

基于源数据多次渲染元素或模板块。此指令之值,必须使用特定语法 alias in expression ,为当前遍历的元素提供别名:

<div v-for="item in items">
  {{ item.text }}
</div>

另外也可以为数组索引指定别名 (或者用于对象的键):

<div v-for="(item, index) in items"></div>
<div v-for="(val, key) in object"></div>
<div v-for="(val, name, index) in object"></div>

v-for 的默认行为会尝试原地修改元素而不是移动它们。要强制其重新排序元素,你需要用特殊属性 key 来提供一个排序提示:

如果该数组可能是会变化的,不要使用 index 作为 key,可以使用固定的某个值,比如user_id

<div v-for="item in items" :key="item.id">
  {{ item.text }}
</div>

数组中使用 v-for

<div id="app">
  <ul>
    <li v-for="(item, index) in list">
      index: ${ index }, name: ${ item.name }
    </li>
  </ul>
</div>
var vm = new Vue({
  el: '#app',
  delimiters: ['${', '}'],
  data: {
    list: [
      { id: '123456789', name: ' 1111' },
      { id: '234567890', name: ' 2222' },
      { id: '345678901', name: ' 3333' },
    ],
  },
});

对象中使用 v-for

<div id="app">
  <ul>
    <li v-for="(item, key, index) in list">
      index: ${ index }, key: ${ key }, name: ${ item.name }
    </li>
  </ul>
</div>
var vm = new Vue({
  el: '#app',
  delimiters: ['${', '}'],
  data: {
    list: {
      '123456789': { name: '選項 1' },
      '234567890': { name: '選項 2' },
      '345678901': { name: '選項 3' },
    },
  },
});

在迭代中使用 v-for

div>
  <span v-for="n in 10">${ n }</span>
</div>

<template标签

<div id="app">
  <ul>
    <template v-for="(item, index) in list">
      <li>index: ${ index }, name: ${ item.name }</li>
    </template>
  </ul>
</div>

其他

从 2.6 起,v-for 也可以在实现了可迭代协议的值上使用,包括原生的 MapSet。不过应该注意的是 Vue 2.x 目前并不支持可响应的 MapSet 值,所以无法自动探测变更。

当和 v-if 一起使用时,v-for 的优先级比 v-if 更高。详见列表渲染教程

v-for 的详细用法可以通过以下链接查看教程详细说明。

参考

Key 说明

由于效能考虑,在默认的状况下,Vue.js 会尽量重复使用已渲染好的元素。

若不设定 key 值,不会重新渲染元素,只会部份更新。

不使用 Key 的演示

<div id="app">
  <ul>
    <li v-for="(item, index) in list">${ index } <input type="text" :placeholder="item.name" /></li>
  </ul>
</div>
var vm = new Vue({
  el: '#app',
  delimiters: ['${', '}'],
  data: {
    list: [
      { id: '123456789', name: '選項 1' },
      { id: '234567890', name: '選項 2' },
      { id: '345678901', name: '選項 3' },
    ],
  },
});

初始画面,用户分别在每个输入框中输入文字。

使用改变元素顺序后,虽然元素被更新,但用户的输入被保留,这是因为元素并没有被重新渲染,而只是部份更新而已。vm.list.reverse()

使用 Key

修改上例,每个 都使用 绑定一个属性 并设定唯一值,目的是确保每个元素的唯一性,

当元素更新,例如改变顺序时,有可识别唯一性的 key 来确保重新渲染。<li>v-bind:key

<div id="app">
  <ul>
    <li v-for="(item, index) in list" :key="item.id">
      ${ index } <input type="text" :placeholder="item.name" />
    </li>
  </ul>
</div>
var vm = new Vue({
  el: '#app',
  delimiters: ['${', '}'],
  data: {
    list: [
      { id: '123456789', name: '選項 1' },
      { id: '234567890', name: '選項 2' },
      { id: '345678901', name: '選項 3' },
    ],
  },
});

按照不更新的那种更改顺序,设定 key 值便会重新更新;

所有会更改数组的方法

下面这些方法是会更改数组的,需要记住

'push',   新增元素。
'pop',    删除最后一个
'shift',  删除第一个 (即最旧的) 元素。
'unshift',加入元素至第一个位置。

'splice', 加入或移除元素。
'sort',   由小至大排序。
'reverse' 元素反序排列

显示处理后的结果

v-for 迭代的数据是使用 computedmethods 处理后的结果。 (不是直接的 Data 数据)

例如:显示数量大于 6 的水果。

<div id="app">
  <ul>
    <li v-for="item in filteredFrouts">${ item.name }</li>
  </ul>
</div>
var vm = new Vue({
  el: '#app',
  delimiters: ['${', '}'],
  data: {
    frouts: [
      {
        name: 'Apple',
        count: 10,
      },
      {
        name: 'Orange',
        count: 5,
      },
      {
        name: 'Banana',
        count: 20,
      },
    ],
  },
  computed: {
    filteredFrouts: function() {
      return this.frouts.filter(function(item) {
        return item.count > 6;
      });
    },
  },
});

v-for 与 v-if 优先权的比较

v-for的优先权高于v-if,因此当两者皆出现在同一个元素上时,v-if会随着v-for重覆执行数次。

如下所示,v-if 会执行 10 次,每次都会判断 n 除以 2 的余数是否为 1,若为 1 则显示,否则就隐藏。

<ul>
  <li v-if="n % 2 === 1" v-for="n in 10">${ n }</li>
</ul>

注意,v-for 的个数范围判断条件成立后,才会轮到 v-if 来判断显示与否。

这是什么意思呢?来看下一个例子就知道了。

如下所示,这里同时出现了 v-for、v-if 和 v-else 三个指令。

在这个例子中,我们试图印出 list 阵列的元素内容,而目前 list 是空阵列,没有任何项目可显示。

因此,当 v-for 在判断 item in list 时,发现条件不成立,就不去做 v-if 和 v-else 判断了,导致原本没有元素印出时应该要提示的「Nothing could show.」都没有出现:(

<div id="app">
  <div v-if="list.length !== 0" v-for="item in list">
    <div>${ item.name }</div>
  </div>
  <div v-else>
    Nothing could show.
  </div>
</div>
new Vue({
  el: '#app',
  delimiters: ['${', '}'],
  data: {
    list: [],
  },
});

总结,由于 v-for 优先权较高,当 v-for 执行完条件判断后,若条件不成立,则后面的 v-if 也不会执行,接着忽略了其后的 v-else。

解决办法

解法如下,让 v-for 来判断 list 是否有内容的状况,v-if 只要负责处理项目为 0 个的情况即可。

<div id="app">
  <div v-for="item in list">
    <div>${ item.name }</div>
  </div>
  <div v-if="list.length === 0">
    Nothing could show.
  </div>
</div>

参考:https://cythilya.github.io/2017/04/27/vue-list-rendering/

AXIHE / 精选资源

浏览全部教程

面试题

学习网站

前端培训
自己甄别

前端书籍

关于朱安邦

我叫 朱安邦,阿西河的站长,在杭州。

以前是一名平面设计师,后来开始接接触前端开发,主要研究前端技术中的JS方向。

业余时间我喜欢分享和交流自己的技术,欢迎大家关注我的 Bilibili

关注我: Github / 知乎

于2021年离开前端领域,目前重心放在研究区块链上面了

我叫朱安邦,阿西河的站长

目前在杭州从事区块链周边的开发工作,机械专业,以前从事平面设计工作。

2014年底脱产在老家自学6个月的前端技术,自学期间几乎从未出过家门,最终找到了满意的前端工作。更多>

于2021年离开前端领域,目前从事区块链方面工作了