用把一个数组对应为一组元素
用
v-for
指令基于一个数组来渲染一个列表。v-for
指令需要使用item in items
形式的特殊语法,其中items
是元数据数组,而item则是被迭代的数组元素的别名。
列:
{{item.message}}
//数据
data() {
return {
items:[
{message:"A"},
{message:"B"},
{message:"C"},
{message:"D"}
]
}
},
在v-for
语句块中,可以访问所有福作用域的属性。v-for
还支持一个可选的第二个参数,即当前项的索引。
{{parentTitle}} -- {{index}} -- {{item.message}}
data() {
return {
parentTitle:"标题",
items:[
{message:"A"},
{message:"B"},
{message:"C"},
{message:"D"}
]
}
},
也可以用of
替代in
作为分隔符,因为它更接近js迭代器的语法:
在v-for
里使用对象
也可以用v-for
来遍历一个对象的属性。
{{value}}
data() {
return {
object:{
title:'平凡的世界',
auther:'路遥',
publishedAt:'2020-09-09'
}
}
},
也可以提供第二个参数作为属性名(键名):
{{name}}:{{value}}
还可以用第三个参数作为索引:
{{ index }}. {{ name }}: {{ value }}
在遍历对小时,会按
Object.keys()
的结果遍历,但是不能保证它的结果在不同的js引擎下都一致。
维护状态
当vue正在使用v-for
渲染元素列表时,他默认使用的就是就地更新
的策略。如果数据项的顺序改变,vue将不会移动DOM元素来匹配数据项的顺序,而是就地更新每个元素,并且确保他们在每个索引位置正确渲染。
这个默认模式是高效的,但是只适用于不依赖子组件状态或临时DOM状态(例如;表单输入值)的列表渲染输出。
为了给vue一个提示,以便他能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为没项提供一个唯一key
的属性:
建议尽可能在使用v-for
的时候提供key
属性。
不要使用对象或数组之类的非基本类型值作为
v-for
的key
。请使用字符串或者数值类型的值。
数组更新检测
变更方法
vue将被侦听的数组的变更方法进行了包裹,所以他们也将会触发视图更新。这些包裹过得方法包括:
-
push()
向数组的末尾添加新的元素 -
pop()
删除数组中的最后一个元素 -
shift()
删除数组的第一个元素 -
unshift()
在数组的开头添加元素 -
splice()
在数组的第2位置添加一个元素 -
sort()
数组排序 -
reverse()
数组中的元素翻转
替换数组
变更方法:顾名思义,会变更调用了这些方法的原始数组。相比之下,也有非变更方法,如:
filter()
、concat()
、slice()
。它们不会变更原数组,而总是返回一个新数组,当使用非变更方法时,可以用新数组替换旧数组:
example1.items = example1.items.filter(function (item) {
return item.message.match(/Foo/)
})
注意事项
由于js的限制,vue不能检测数组和对象的变化。
显示过滤/排序后的结果
若想要显示一个数组经过过滤或排序后的版本,而不实际变更或充值原始数据。在这种情况下,可以创建一个计算属性,来返回过滤或排序后的数组。
例如:
{{ n }}
data: {
numbers: [ 1, 2, 3, 4, 5 ]
},
computed: {
//定义一个计算属性
evenNumbers: function () {
return this.numbers.filter(function (number) {
return number % 2 === 0
})
}
}
在计算属性不适用的情况下(如,在嵌套v-for
循环中)你可以适用一个方法:
- {{ n }}
data: {
sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]]
},
methods: {
//定义一个方法
even: function (numbers) {
return numbers.filter(function (number) {
return number % 2 === 0
})
}
}
在v-for
里使用值范围
v-for
也可以接受整数,在这种情况下,他会把模板重复对应次数。
{{ n }}
结果:
1 2 3 4 5 6 7 8 9 10
在
上使用v-for
类似于v-if
,你也可以利用带有v-for
的来循环渲染一段包含多个元素的内容。
比如:
- {{ item.msg }}
v-for
与v-if
一同使用
注意我们 不 推荐在同一元素上使用
v-if
和v-for
。
当他们处于同一节点,v-for
的优先级比v-if
更高,这意味着v-if
将分别重复运行于每个v-for
循环中。当你只想为部分项渲染节点时,这种优先级的机制会十分有用,如:
{{ todo }}
上面代码将值渲染未完成的todo。
而如果你的目的是有条件的跳过循环的执行,那么可以将v-if
置于外层元素(或)上。如:
-
{{ todo }}
No todos left!
在组件上使用v-for
在自定义组件上,你可以像在任何普通元素上一样使用
v-for
。
然而,任何数据都不会被自动传递到组件里,因为组件有自己独立的作用域。为了把迭代数据传递到组件里,我们要使用prop:
不自动将item
注入到组件里的原因是,这会使得组件与v-for
的运作紧密耦合。明确组件数据的来源能够使组件在其他场合重复使用。
以下是一个简单的todo列表的完整的例子:
注意:这里的
is="todo-item"
属性。这种做法在使用DOM模板时是十分必要的,因为在元素内只有
元素会被看作有效内容。这样做的实现的效果与
相同,但是可以避开一些潜在的浏览器解析错误。
Vue.component('todo-item', {
template: '\
\
{{ title }}\
\
\
',
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 = ''
}
}
})