v-for 指令 — 数组
- v-for 指令基于一个数组来渲染一个列表
- 使用
item in items
或(item, index) in items
形式的特殊语法 -
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
- 当 Vue 正在更新使用
v-for
渲染的元素列表时,默认使用“就地更新”的策略 - 只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出
- 为每项提供一个唯一
key
属性,便于跟踪每个节点的身份,从而重用和重新排序现有元素
<div v-for="item in items" v-bind:key="item.id">
<!-- 内容 -->
</div>
- 不要使用对象或数组之类的非基本类型值作为
v-for
的key
数组更新检测
变异方法 (mutation method)
- Vue 将被侦听的数组的变异方法进行了包裹,变异方法将会触发视图更新
- 改变调用了变异方法的原始数组
-
push()
——接收任意数量的参数,把逐个添加到数组末尾,并返回修改后数组的长度 -
pop()
——从数组末尾移除后一项,减少数组的 length 值,返回移除的项 -
shift()
——移除数组中的第一个项并返回该项,同时将数组长度减 1 -
unshift()
——能在数组前端添加任意个项并返回新数组的长度 -
splice()
——向数组的中部插入项(删除项的起始位置、删除的项数、插入任意数量的项) -
sort()
——按升序排列数组项,可以接收一个比较函数作为参 数 -
reverse()
——反转数组项的顺序
替换数组
- 不会改变原始数组,而总是返回一个新数组
- 当使用非变异方法时,可以用新数组替换旧数组
example1.items = example1.items.filter(function (item) {
return item.message.match(/Foo/)
})
filter()
concat()
slice()
注意事项
由于 JavaScript 的限制,Vue 不能检测以下数组的变动,在界面为非响应式
-
利用索引直接设置一个数组项时
vm.items[2] = 'newValue'
-
修改数组的长度时
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 指令 — 对象
- 用
v-for
来遍历一个对象的属性 - 使用
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 不能检测对象属性的添加或删除
- 对于已经创建的实例,Vue 不允许动态添加根级别的响应式属性
解决方法
Vue.set(object, propertyName, value)
方法向嵌套对象添加响应式属性
添加单个属性
Vue.set(vm.userProfile, 'age', 27)
添加多个属性
vm.userProfile = Object.assign({}, vm.userProfile, {
age: 27,
favoriteColor: 'Vue Green'
})
显示过滤/排序后的结果
-
显示一个数组经过过滤或排序后的版本,而不实际改变或重置原始数据
计算属性
<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
- 利用带有
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 一同使用
-
v-for
的优先级比v-if
更高
<li v-for="todo in todos" v-if="!todo.isComplete">
{{ todo }}
</li>
在组件上使用 v-for
- 当在组件上使用
v-for
时,key
现在是必须的 - 任何数据都不会被自动传递到组件里,组件有独立的作用域
<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 = ''
}
}
})