v-for 是Vue用来遍历渲染一组数据的,例如数据数组,数据对象。
v-for 遍历数组
遍历的第一个值是数组内的元素,第二个是数组的索引。
普通元素
字符串数组
<template>
<div>
<ul>
<li v-for="(item, index) in stringArray" :key="index">
{{ index }} - {{ item }}
</li>
</ul>
</div>
</template>
<script>
export default {
data () {
return {
stringArray: [
'张三丰',
'张翠山',
'张无忌'
]
}
}
}
</script>
使用值范围
<template>
<div>
<ul>
<li v-for="n in 10" :key="n">{{ n }}</li>
</ul>
</div>
</template>
对象数据
<template>
<div>
<ul>
<li v-for="(item, index) in objectArray" :key="index">
{{ index }} - {{ item.name }}
</li>
</ul>
</div>
</template>
<script>
export default {
data () {
return {
objectArray: [
{ name: '武当山' },
{ name: '峨眉山' },
{ name: '光明顶' }
]
}
}
}
</script>
v-for 遍历对象
遍历的第一个是对象的值,第二个是对象的key,第三个则是对象元素的索引。
<template>
<div>
<ul>
<!-- 若遍历了一个值,那么这个值则是对象的value -->
<li v-for="item in objects" :key="item">
{{ item }}
</li>
<!-- 若遍历了二个值,那么则第一个是value,第二个是key -->
<li v-for="(item, k) in objects" :key="k">
{{ k }} - {{ item }}
</li>
<!-- 若遍历了三个值,那么则第一个是value,第二个是key,第三个是对象元素的index,也就是索引 -->
<li v-for="(item, k, i) in objects" :key="k">
{{ k }} - {{ item }} - {{ i }}
</li>
</ul>
</div>
</template>
<script>
export default {
data () {
return {
objects: {
name: '张无忌',
age: 80
}
}
}
}
</script>
数据更新
由于 JavaScript 的限制,Vue 不能检测数组和对象的变化。
尽管如此我们还是有一些办法来回避这些限制并保证它们的响应性。
因此当你利用中括号([])的方式直接设置一个数组或者对象的选项的时候,例如:vm.items[indexOfItem] = newValue
,是无法在视图响应更新的,当然也会有其他无法侦听到的,例如数组的长度等等。
数组数据更新
所以我们需要使用以下的方法来规避此类问题,侦听数据数组的变化。
push()
// 可向数组的末尾添加一个或多个元素,并返回新的长度。pop()
// 用于删除并返回数组的最后一个元素。shift()
// 用于把数组的第一个元素从其中删除,并返回第一个元素的值。unshift()
// 可向数组的开头添加一个或更多元素,并返回新的长度。splice()
// 向/从数组中添加/删除项目,然后返回被删除的项目。sort()
// 用于对数组的元素进行排序。reverse()
// 用于颠倒数组中元素的顺序。
实例演示:
<template>
<div>
</div>
</template>
<script>
export default {
data () {
return {
list: [
'张无忌',
'小昭',
'赵敏',
'阿朱',
'周芷若'
]
}
},
created () {
// push() 可向数组的末尾添加一个或多个元素,并返回新的长度。
console.log(this.list.push('张翠山', '张三丰'))
console.log(this.list)
// pop() 用于删除并返回数组的最后一个元素。
console.log(this.list.pop())
console.log(this.list)
// shift() 用于把数组的第一个元素从其中删除,并返回第一个元素的值。
console.log(this.list.shift())
console.log(this.list)
// unshift() 可向数组的开头添加一个或更多元素,并返回新的长度。
console.log(this.list.unshift('武当山', '光明顶'))
console.log(this.list)
// splice() 向/从数组中添加/删除项目,然后返回被删除的项目。
console.log(this.list.splice(1, 1))
console.log(this.list)
// sort() 用于对数组的元素进行排序。
console.log(this.list.sort())
// reverse() 用于颠倒数组中元素的顺序。
console.log(this.list.reverse())
}
}
</script>
对象数据更新
由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的。
例如:
# 官方例子
var vm = new Vue({
data:{
a:1
}
})
// `vm.a` 是响应的
vm.b = 2
// `vm.b` 是非响应的
使用 set 方法更新对象数据元素。
<template>
<div>
<ul>
<template v-for="v in list">
<li :key="v">
{{ v }}
</li>
</template>
</ul>
<button @click="update">更新</button>
</div>
</template>
<script>
export default {
data () {
return {
list: {
name: '张三丰',
age: '张无忌'
}
}
},
methods: {
update () {
this.$set(this.list, 'name', '兰玉磊最无敌')
}
}
}
</script>
v-for 和 v-if 一起使用
当它们处于同一节点,v-for
的优先级比 v-if
更高,这意味着 v-if
将分别重复运行于每个 v-for
循环中。当你只想为部分项渲染节点时,这种优先级的机制会十分有用,但是我们的编辑器会给我们报错,因此推荐使用 template 标签来兼容这种问题。
<template>
<div>
<ul>
<template v-for="n in 10">
<li :key="n" v-if="n !== 2">
{{ n }}
</li>
</template>
</ul>
</div>
</template>
当想要 v-if 的优先级高的时候,则交换以下 v-for 和 v-if 的位置即可,例如:
<template>
<div>
<ul>
<template v-if="i === 10">
<li v-for="n in i" :key="n">
{{ n }}
</li>
</template>
</ul>
</div>
</template>
<script>
export default {
data () {
return {
i: 10
}
}
}
</script>
key
在介绍 v-if 的时候,我们也聊到了这个key,但是更多的时候,是介绍这个key的优点,那么这里我们说说,如果key使用不当,会造成什么样的bug。
Vue 默认会使用一种最大限度减少动态元素并且尽可能的尝试 就地修改 / 复用相同类型元素 的算法,也就是说,如果数据的顺序别改变或者打乱,Vue 不会移动DOM元素来匹配数据的顺序,而是就地修改每个元素,并且确保它们在每个索引位置正确渲染。
实例演示,这个是一个有bug的演示,方便了解 key 在 v-for 中的作用:
<template>
<div>
<ul>
<template v-for="(n, i) in list">
<li :key="i" :id="i === 0 ? 'test': ''">
<input type="checkbox">
{{ n }}
</li>
</template>
</ul>
<button @click="add">添加</button>
</div>
</template>
<script>
export default {
data () {
return {
list: [1, 2, 3, 4, 5, 6, 7, 8, 9]
}
},
methods: {
add () {
this.list.unshift(10)
}
}
}
</script>