10.Vue基本语法介绍七

引言:

这一节介绍有关列表,列表渲染的基本知识,

加油加油!!


列表渲染

v-for把一个数组对应为一组元素

我们可以用 v-for 指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名。

1
2
3
4
5
<ul id="example-1">
<li v-for="item in items">
{{ item.message }}
</li>
</ul>
1
2
3
4
5
6
7
8
9
var example1 = new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})

v-for块中我们可以访问所有父作用域的属性,v-for还支持一个可选的第二个参数,即当前项的索引值

1
2
3
4
5
<ul id="example-2">
<li v-for="(item, index) in items">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
</ul>
1
2
3
4
5
6
7
8
9
10
var example2 = new Vue({
el: '#example-2',
data: {
parentMessage: 'Parent',
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})

其中的in我们可以换成of,这两个都可以

当我们需要包裹多个div时,又不想要多用一个div,
就可以使用模板占位符<template><template>来替代这个div

v-for里使用对象

也可以用v-for来遍历一个对象的属性

1
2
3
4
5
<ul id="v-for-object" class="demo">
<li v-for="value in object">
{{ value }}
</li>
</ul>
1
2
3
4
5
6
7
8
9
10
new Vue({
el: '#v-for-object',
data: {
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
})

也可以提供键名

1
2
3
<div v-for="(value, name) in object">
{{ name }}: {{ value }}
</div>

在此之上还可以加上索引

1
2
3
<div v-for="(value, name, index) in object">
{{ index }}. {{ name }}: {{ value }}
</div>

在遍历对象时,会按 Object.keys() 的结果遍历,但是不能保证它的结果在不同的 JavaScript 引擎下都一致。

维护状态

当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。

如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素

只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出

所以我们需要给每一项提供一个唯一的key属性来确保Vue能正确的跟踪每一个节点

1
2
3
<div v-for="item in items" v-bind:key="item.id">
<!-- 内容 -->
</div>

注意:

不要使用对象或数组之类的非基本类型值作为 v-for 的 key。请用字符串或数值类型的值。

数组更新检测

变异方法

Vue 将被侦听的数组的变异方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

替换数组

我们也可以用不变异的方法,返回一个新的数组代替旧的数组

  • filter()
  • concat()
  • slice()

注意事项

Vue不能检测到如下数组的变动

  1. 当使用索引直接设置一个数组项的时候,例如:vm.items[indexOfItem] = newValue
  2. 当修改数组长度的时候,例如vm.items.length = newLength

例如:

1
2
3
4
5
6
7
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
})
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的

为了解决第一类问题,以下两种方式都可以实现和 vm.items[indexOfItem] = newValue 相同的效果,同时也将在响应式系统内触发状态更新:

1
2
3
4
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)

也可以使用 vm.$set 实例方法,该方法是全局方法 Vue.set 的一个别名:

1
vm.$set(vm.items, indexOfItem, newValue)

为了解决第二类问题,你可以使用 splice:

1
vm.items.splice(newLength)

对象变更检测注意事项

Vue不能检测对象属性的添加或删除

1
2
3
4
5
6
7
8
9
var vm = new Vue({
data: {
a: 1
}
})
// `vm.a` 现在是响应式的

vm.b = 2
// `vm.b` 不是响应式的

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

但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式属性

例如:

1
2
3
4
5
6
7
var vm = new Vue({
data: {
userProfile: {
name: 'Anika'
}
}
})

可以添加一个新的 age 属性到嵌套的 userProfile 对象:

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

还可以使用 vm.$set 实例方法,它只是全局 Vue.set 的别名:

1
vm.$set(vm.userProfile, 'age', 27)

有时你可能需要为已有对象赋值多个新属性,比如使用 Object.assign() _.extend()

在这种情况下,你应该用两个对象的属性创建一个新的对象

不要这样做

1
2
3
4
Object.assign(vm.userProfile, {
age: 27,
favoriteColor: 'Vue Green'
})

而要这样做

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

显示过滤/排序后的结果

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

在这种情况下,可以创建一个计算属性,来返回过滤或排序后的数组。

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

在计算属性不适用的情况下 (例如,在嵌套 v-for 循环中) 你可以使用一个方法:

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

v-for 里使用值范围

v-for 也可以接受整数。在这种情况下,它会把模板重复对应次数

1
2
3
4
5
6
7
8
9
10
11
12
<body>

<div id='demo'>
<span v-for="n in 10">{{ n }} </span>
</div>

<script>
new Vue({
el:'#demo',
})
</script>
</body>

<template> 上使用 v-for

类似于 v-if,你也可以利用带有 v-for 的