列表渲染

    1. Vue.createApp({
    2. data() {
    3. return {
    4. items: [{ message: 'Foo' }, { message: 'Bar' }]
    5. }
    6. }
    7. }).mount('#array-rendering')

    结果:

    See the Pen by Vue (@Vue) on .

    v-for 块中,我们可以访问所有父作用域的 property。v-for 还支持一个可选的第二个参数,即当前项的索引。

    1. <ul id="array-with-index">
    2. <li v-for="(item, index) in items">
    3. {{ parentMessage }} - {{ index }} - {{ item.message }}
    4. </li>
    5. </ul>
    1. Vue.createApp({
    2. data() {
    3. return {
    4. parentMessage: 'Parent',
    5. items: [{ message: 'Foo' }, { message: 'Bar' }]
    6. }
    7. }
    8. }).mount('#array-with-index')

    结果:

    See the Pen v-for with Array and index by Vue () on CodePen.

    你也可以用 of 替代 in 作为分隔符,因为它更接近 JavaScript 迭代器的语法:

    1. <div v-for="item of items"></div>

    v-for 里使用对象

    你也可以用 v-for 来遍历一个对象的 property。

    1. <ul id="v-for-object" class="demo">
    2. <li v-for="value in myObject">
    3. {{ value }}
    4. </li>
    5. </ul>
    1. Vue.createApp({
    2. data() {
    3. return {
    4. myObject: {
    5. title: 'How to do lists in Vue',
    6. author: 'Jane Doe',
    7. publishedAt: '2016-04-10'
    8. }
    9. }
    10. }

    结果:

    See the Pen by Vue (@Vue) on .

    你也可以提供第二个的参数为 property 名称 (也就是键名 key):

    See the Pen v-for with Object and key by Vue () on CodePen.

    还可以用第三个参数作为索引:

    1. <li v-for="(value, name, index) in myObject">
    2. {{ index }}. {{ name }}: {{ value }}
    3. </li>

    See the Pen by Vue (@Vue) on .

    提示

    维护状态

    当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。

    这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出

    为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key attribute:

    1. <div v-for="item in items" :key="item.id">
    2. </div>

    建议尽可能在使用 v-for 时提供 key attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。

    因为它是 Vue 识别节点的一个通用机制,key 并不仅与 v-for 特别关联。后面我们将在指南中看到,它还具有其它用途。

    提示

    不要使用对象或数组之类的非基本类型值作为 v-for 的 key。请用字符串或数值类型的值。

    更多 key attribute 的细节用法请移步至 key 的 API 文档

    Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:

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

    你可以打开控制台,然后对前面例子的 items 数组尝试调用变更方法。比如 example1.items.push({ message: 'Baz' })

    替换数组

    变更方法,顾名思义,会变更调用了这些方法的原始数组。相比之下,也有非变更方法,例如 filter()concat()slice()。它们不会变更原始数组,而总是返回一个新数组。当使用非变更方法时,可以用新数组替换旧数组:

    1. example1.items = example1.items.filter(item => item.message.match(/Foo/))

    你可能认为这将导致 Vue 丢弃现有 DOM 并重新渲染整个列表。幸运的是,事实并非如此。Vue 为了使得 DOM 元素得到最大范围的重用而实现了一些智能的启发式方法,所以用一个含有相同元素的数组去替换原来的数组是非常高效的操作。

    显示过滤/排序后的结果

    有时,我们想要显示一个数组经过过滤或排序后的版本,而不实际变更或重置原始数据。在这种情况下,可以创建一个计算属性,来返回过滤或排序后的数组。

    例如:

    1. <li v-for="n in evenNumbers">{{ n }}</li>
    1. data() {
    2. return {
    3. numbers: [ 1, 2, 3, 4, 5 ]
    4. }
    5. },
    6. computed: {
    7. evenNumbers() {
    8. return this.numbers.filter(number => number % 2 === 0)
    9. }
    10. }
    1. <ul v-for="numbers in sets">
    2. <li v-for="n in even(numbers)">{{ n }}</li>
    3. </ul>

    v-for 里使用值的范围

    v-for 也可以接受整数。在这种情况下,它会把模板重复对应次数。

    1. <div id="range" class="demo">
    2. <span v-for="n in 10">{{ n }} </span>
    3. </div>

    结果:

    See the Pen by Vue (@Vue) on .

    类似于 v-if,你也可以利用带有 v-for<template> 来循环渲染一段包含多个元素的内容。比如:

    1. <ul>
    2. <template v-for="item in items">
    3. <li>{{ item.msg }}</li>
    4. <li class="divider" role="presentation"></li>
    5. </template>
    6. </ul>

    v-forv-if 一同使用

    TIP

    注意我们推荐在同一元素上使用 v-ifv-for。更多细节可查阅风格指南

    当它们处于同一节点,v-if 的优先级比 v-for 更高,这意味着 v-if 将没有权限访问 v-for 里的变量:

    1. <!-- This will throw an error because property "todo" is not defined on instance. -->
    2. {{ todo }}
    3. </li>

    可以把 v-for 移动到 <template> 标签中来修正:

    1. <template v-for="todo in todos">
    2. <li v-if="!todo.isComplete">
    3. {{ todo }}
    4. </li>
    5. </template>

    在组件上使用 v-for

    在自定义组件上,你可以像在任何普通元素上一样使用 v-for

      然而,任何数据都不会被自动传递到组件里,因为组件有自己独立的作用域。为了把迭代数据传递到组件里,我们要使用 props:

      1. <my-component
      2. v-for="(item, index) in items"
      3. :item="item"
      4. :index="index"
      5. :key="item.id"
      6. ></my-component>

      不自动将 item 注入到组件里的原因是,这会使得组件与 v-for 的运作紧密耦合。明确组件数据的来源能够使组件在其他场合重复使用。

      下面是一个简单的 todo 列表的完整例子:

      1. const app = Vue.createApp({
      2. data() {
      3. return {
      4. newTodoText: '',
      5. todos: [
      6. {
      7. id: 1,
      8. title: 'Do the dishes'
      9. },
      10. {
      11. id: 2,
      12. title: 'Take out the trash'
      13. },
      14. {
      15. id: 3,
      16. title: 'Mow the lawn'
      17. }
      18. ],
      19. nextTodoId: 4
      20. }
      21. },
      22. methods: {
      23. addNewTodo() {
      24. this.todos.push({
      25. id: this.nextTodoId++,
      26. title: this.newTodoText
      27. })
      28. this.newTodoText = ''
      29. }
      30. }
      31. })
      32. app.component('todo-item', {
      33. template: `
      34. <li>
      35. {{ title }}
      36. <button @click="$emit('remove')">Remove</button>
      37. </li>
      38. `,
      39. props: ['title']
      40. })

      See the Pen by Vue (@Vue) on .