原文:
https://cn.vuejs.org/v2/guide/list.html#v-for-with-v-if
用v-for把一个数组对应为一组元素
` v-for `指令需要会用`item in items`形式的特殊语法,`items`是元数据数组并且`item`是数组元素迭代的别名。
在`v-for`块中,我们拥有对父作用域属性的完全访问权限。`v-for`还支持一个可选的第二个参数为当前项的索引。
<ul id="example-2">
<li v-for="(item, index) in items">
</li>
</ul>
var example2 = new Vue({
el: '#example-2',
data: {
parentMessage: 'Parent',
items:[
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
也可以用of
代替in
作为分隔符,因为它是最接近JavaScript迭代器的语法:
<div v-for="item of items"> </div>
对象的属性迭代 v-for
- 提供一个参数为迭代的别名
<ul id="v-for-object" class="demo">
<li v-for="value in object">
{{ value }}
</li>
</ul>
new Vue({
el: '#v-for-object',
data: {
object: {
firstName: 'John',
lastName: 'Doe',
age: 30
}
}
})
- 提供第二个的参数为键名:
<div v-for="(value, key) in object"></div>
- 提供第三个参数为索引
<div v-for="(value, key, index) in object">
{{ index }}. {{ key }}: {{ value }}
</div>
提示: 在遍历对象时,是按
object.keys()
的结果遍历,但是不能保证 它的结果在不同的JavaScript引擎下是一致的
key
当vue.js正在更新已渲染过的元素列表时,它默认用就地复用策略。如果数据项的顺序被改变,Vue将不会移动DOM来匹配数据项的顺序,而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。这个类似Vue 1.x的track-by="$index"
这个默认的模式是高效的,但是只适用于不依赖组价状态或临时DOM状态(例如:表单输入值)的列表渲染输出
为了给Vue一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,因而需要没每项提供一个唯一key
属性。理想的key
值是每项都有的唯一id。
这个特殊的属性相当于Vue 1.x的track-by
,但它的工作方式类似于一个属性,所以需要用v-bind
来绑定动态值:
<div v-for="item in items" :key="item.id">
建议尽可能在使用
v-for
时提供key
,除非遍历输出的DOM内容非常简单,或者是可以依赖默认行为以获取性能上的提升。
因为它是Vue识别节点的一个通用机制,key
并不与v-for
特别关联,key
还具有其他用途
不要使用对象或数组之类的给原始类型值作为
v-for
的key
。用字符串或数类型的值取而代之。
数组更新检测
变异方法
vue包含一组观察数组的变异方法,所以他们也将会触发视图更新。
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
替换数组
变异方法,会改变被这些方法调用的原始狐族。相比之下,也有非变异方法,例如:filter()
,concat()
和slice()
。这些不会改变原始数组,但总是返回一个新的数组。当使用非变异方法时,可以用心数组替换旧数组
example.items = example.items.filter(function (item){
return item.message.match(/Foo/)
})
注意事项
由于JavaScript的限制,vue不能检测以下变动的数组:
1. 利用索引值直接设置一个项时,例如:vm.items[indexOfItem] = newValue
2. 修改数组的长度时,例如: vm.items.length = newLength
v-for
withv-if
当它们处于同一节点,
v-for
的优先级比v-if
更高,这意味着v-if
将分别运行于每个v-for
循环中。
一个组件的v-for
2.2.0+的版本里,当在组件中使用
v-for
时,key
现在是必须的
<my-component
v-for="(item, index) in items"
v-bind:item="item"
v-bind:index="index"
v-bind:key="item.id">
</my-component>
不自动将 item 注入到组件里的原因是,这会使得组件与 v-for 的运作紧密耦合。明确组件数据的来源能够使组件在其他场合重复使用。
下面是一个简单的TODOlist的完整例子
<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>
注意这里的
is="todo-item"
属性。这种做法在使用 DOM 模板时是十分必要的,因为在<ul>
元素内只有<li>
元素会被看作有效内容。这样做实现的效果与<todo-item>
相同,但是可以避开一些潜在的浏览器解析错误。查看 DOM 模板解析说明 来了解更多信息。
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 = ''
}
}
})