7. 列表渲染

v-for 指令 — 数组

  1. v-for 指令基于一个数组来渲染一个列表
  2. 使用 item in items(item, index) in items形式的特殊语法
  3. items是源数据数组, item 是被迭代的数组元素的别名
<ul id="example-2">
  <li v-for="(item, index) in items">
    {{ parentMessage }} - {{ index }} - {{ item.message }}
  </li>
</ul>
var example2 = new Vue({
  el: '#example-2',
  data: {
    parentMessage: 'Parent', // v-for 可直接访问
    items: [
      { message: 'Foo' }, //数组内对象为被迭代的item
      { message: 'Bar' }
    ]
  }
})
  • v-for块中,可以访问所有父作用域的属性

  • 可用 of 替代in 作为分隔符

维护状态-key

  1. 当 Vue 正在更新使用 v-for 渲染的元素列表时,默认使用“就地更新”的策略
  2. 只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出
  3. 为每项提供一个唯一 key 属性,便于跟踪每个节点的身份,从而重用和重新排序现有元素
<div v-for="item in items" v-bind:key="item.id">
  <!-- 内容 -->
</div>
  • 不要使用对象或数组之类的非基本类型值作为 v-forkey

数组更新检测

变异方法 (mutation method)

  1. Vue 将被侦听的数组的变异方法进行了包裹,变异方法将会触发视图更新
  2. 改变调用了变异方法的原始数组
  • push()——接收任意数量的参数,把逐个添加到数组末尾,并返回修改后数组的长度
  • pop()——从数组末尾移除后一项,减少数组的 length 值,返回移除的项
  • shift()——移除数组中的第一个项并返回该项,同时将数组长度减 1
  • unshift()——能在数组前端添加任意个项并返回新数组的长度
  • splice()——向数组的中部插入项(删除项的起始位置、删除的项数、插入任意数量的项)
  • sort()——按升序排列数组项,可以接收一个比较函数作为参 数
  • reverse()——反转数组项的顺序

替换数组

  1. 不会改变原始数组,而总是返回一个新数组
  2. 当使用非变异方法时,可以用新数组替换旧数组
example1.items = example1.items.filter(function (item) {
  return item.message.match(/Foo/)
})
  • filter()
  • concat()
  • slice()

注意事项

由于 JavaScript 的限制,Vue 不能检测以下数组的变动,在界面为非响应式

  1. 利用索引直接设置一个数组项时

    vm.items[2] = 'newValue'
    
  2. 修改数组的长度时

    vm.items.length = 3
    

解决问题

vm.items[indexOfItem] = newValue

方式一:

// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
vm.$set(vm.items, indexOfItem, newValue)  //vm.$set 实例方法
Vue.set(items, 2, '响应式新值')

方式二:

// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
vm.items.splice(2, 1, '响应式新值')

vm.items.length = newLength

vm.items.splice(newLength)
vm.items.splice(3)

v-for 指令 — 对象

  1. v-for 来遍历一个对象的属性
  2. 使用 value in object(value, name, index) in object形式的特殊语法
<div v-for="(value, name, index) in object">
  键名-{{ value}}
  键值-{{ name }}
  索引-{{ index}}
</div>
new Vue({
  el: '#v-for-object',
  data: {
    object: {
      title: 'How to do lists in Vue',
      author: 'Jane Doe',
      publishedAt: '2019-10-25'
    }
  }
})
  • 在遍历对象时,会按 Object.keys() 的结果遍历

对象变更检测

注意事项

由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除

  1. 对于已经创建的实例,Vue 不允许动态添加根级别的响应式属性

解决方法

Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式属性

添加单个属性

Vue.set(vm.userProfile, 'age', 27)

添加多个属性

vm.userProfile = Object.assign({}, vm.userProfile, {
  age: 27,
  favoriteColor: 'Vue Green'
})

显示过滤/排序后的结果

  1. 显示一个数组经过过滤或排序后的版本,而不实际改变或重置原始数据

    计算属性

    <li v-for="n in evenNumbers">{{ n }}</li>
    
    data: {
     number: [ 1, 2, 3, 4, 5 ]
    },
    computed: {
     evenNumbers: function() {
         return this.number.fliter( function(number) {
             return number % 2 === 0
         })
     }
    }
    

    方法

    <li v-for="n in even(numbers)">{{ n }}</li>
    
    data: {
      numbers: [ 1, 2, 3, 4, 5 ]
    },
    methods: {
      even: function (numbers) {
        return numbers.filter(function (number) {
          return number % 2 === 0
        })
      }
    }
    

在 <template> 上使用 v-for

  1. 利用带有 v-for<template> 来循环渲染一段包含多个元素的内容
<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>

v-for 与 v-if 一同使用

  1. v-for 的优先级比 v-if 更高
<li v-for="todo in todos" v-if="!todo.isComplete">
  {{ todo }}
</li>

在组件上使用 v-for

  1. 当在组件上使用 v-for 时,key 现在是必须的
  2. 任何数据都不会被自动传递到组件里,组件有独立的作用域
<my-component v-for="item in items" :key="item.id"></my-component>
<div id="todo-list-example">
  <form v-on:submit.prevent="addNewTodo">
    <label for="new-todo">Add a todo</label>
    <input
      v-model="newTodoText"
      id="new-todo"
      placeholder="E.g. Feed the cat"
    >
    <button>Add</button>
  </form>
  <ul>
    <li
      is="todo-item"
      v-for="(todo, index) in todos"
      v-bind:key="todo.id"
      v-bind:title="todo.title"
      v-on:remove="todos.splice(index, 1)"
    ></li>
  </ul>
</div>
Vue.component('todo-item', {
  template: '\
    <li>\
      {{ title }}\
      <button v-on:click="$emit(\'remove\')">Remove</button>\
    </li>\
  ',
  props: ['title']
})

new Vue({
  el: '#todo-list-example',
  data: {
    newTodoText: '',
    todos: [
      {
        id: 1,
        title: 'Do the dishes',
      },
      {
        id: 2,
        title: 'Take out the trash',
      },
      {
        id: 3,
        title: 'Mow the lawn'
      }
    ],
    nextTodoId: 4
  },
  methods: {
    addNewTodo: function () {
      this.todos.push({
        id: this.nextTodoId++,
        title: this.newTodoText
      })
      this.newTodoText = ''
    }
  }
})
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 主要还是自己看的,所有内容来自官方文档。 介绍 Vue.js 是什么 Vue (读音 /vjuː/,类似于 vie...
    Leonzai阅读 3,373评论 0 25
  • 1. Vue 实例 1.1 创建一个Vue实例 一个 Vue 应用由一个通过 new Vue 创建的根 Vue 实...
    王童孟阅读 1,029评论 0 2
  • 条件渲染 v-if 在<template>元素上使用v-if条件渲染分组 最终的渲染结果将不包含<template...
    oWSQo阅读 787评论 1 0
  • 1.用 v-for 把一个数组对应为一组元素 我们用 v-for 指令根据一组数组的选项列表进行渲染。v-for ...
    Sunshinga阅读 202评论 0 0
  • 一. Vue 实例 以后你可以在 API 参考中查阅到完整的实例属性和方法的列表。 实例生命周期钩子 比如 cre...
    兔子___阅读 346评论 0 0