7.1用 v-for 把一个数组对应为一组元素
<!-- 我们可以用 v-for 指令基于一个数组来渲染一个列表。v-for 指令需要
使用 item in items 形式的特殊语法,其中 items 是源数据数组,而
item 则是被迭代的数组元素的别名。 -->
<ul id="app1">
<li v-for="item in items">{{item.message}}</li>
</ul>
<script>
var vm1 = new Vue({
el: '#app1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
</script>
<!-- 在 v-for 块中,我们可以访问所有父作用域的 property。v-for 还支
持一个可选的第二个参数index,即当前项的索引。 -->
<ul id="app2">
<li v-for="(item , index) in items">{{parentMsg}} -- {{index}} -- {{item.message}}</li>
</ul>
<script>
var vm1 = new Vue({
el: '#app2',
data: {
parentMsg: 'Parent',
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
</script>
<!-- 你也可以用 of 替代 in 作为分隔符,因为它更接近 JavaScript 迭代器的语法: -->
<div v-for="item of items"></div>
7.2在 v-for 里使用对象
<!-- 你也可以用 v-for 来遍历一个对象的 property。操作遍历涉及3个参数:value name index -->
<!-- value:对象属性值 name:对象属性名 index:对象索引 -->
<ul id="app3">
<li v-for="(value ,name ,index) in objs">
{{index + 1}}.{{name}} :{{value}}
</li>
</ul>
<script>
var vm = new Vue({
el: '#app3',
data: {
objs: {
title: 'HarryPotter', //title对应对象属性名,'HarryPotter'对应对象属性值
author: 'JK.Rowling',
type: 'novel',
nation: 'The Britain'
}
}
})
</script>
7.3维护状态
*不太理解
建议尽可能在使用 v-for 时提供 key attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。
因为它是 Vue 识别节点的一个通用机制,key 并不仅与 v-for 特别关联。后面我们将在指南中看到,它还具有其它用途。
不要使用对象或数组之类的非基本类型值作为 v-for 的 key。请用字符串或数值类型的值。
7.4数组更新检测
7.4.1变更方法
Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
你可以打开控制台,然后对前面例子的 items 数组尝试调用变更方法。比如 example1.items.push({ message: 'Baz' })。
7.4.2替换数组
变更方法,顾名思义,会变更调用了这些方法的原始数组。
7.4.3注意事项
注意事项
由于 JavaScript 的限制,Vue 不能检测数组和对象的变化。
7.5 显示过滤/排序后的结果
显示一个数组经过过滤或排序后的版本,而不实际变更或重置原始数据。
在这种情况下,可以创建一个计算属性,来返回过滤或排序后的数组。
<!-- 示例1:通过计算属性过滤 -->
<ul id="app4">
<li v-for="n in evenNumbers">{{n}}</li>
</ul>
<script>
var vm4 = new Vue({
el: '#app4',
data: {
numbers: [1, 2, 3, 4, 5, 6]
},
computed: {
evenNumbers: function () {
// .filter过滤器函数,过滤掉奇数数字
return this.numbers.filter(function (number) {
return number % 2 === 0; //筛选出偶数数字
})
}
}
})
//console.log(vm4.evenNumbers);
</script>
<!-- 示例2:在计算属性不适用的情况下,通过methods过滤 -->
<div id="app5">
<ul v-for="set in sets">
<li v-for="n in even(set)">{{n}}</li>
</ul>
</div>
<script>
var vm5 = new Vue({
el: '#app5',
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
})
}
}
})
//console.log(vm5.sets);
</script>
7.6 在 v-for 里使用值范围
<!-- v-for 也可以接受整数。在这种情况下,它会把模板重复对应次数。 -->
<div id="app6">
<!-- {{n}}重复10次,打印内容为1 2 3 4 5 6 7 8 9 10 -->
<span v-for="n in 10">{{ n }} </span>
</div>
<script>
var vm5 = new Vue({
el: '#app6'
})
</script>
7.7 在 上使用 v-for
<!-- 类似于 v-if,你也可以利用带有 v-for 的 <template> 来循环渲染一段包含多个元素的内容。比如: -->
<div id="app7">
<template v-for="item in items">
<li>{{item.msg}}</li>
</template>
</div>
<script>
var vm7 = new Vue({
el: '#app7',
data: {
items: [
{ msg: 'Donald' },
{ msg: 'Trump' },
{ msg: 'is' },
{ msg: 'over' }
]
}
})
</script>
7.8 v-for 与 v-if 一同使用
7.8.1使用在同一元素上
注意:不推荐在同一元素上使用 v-if 和 v-for。
当它们处于同一节点,v-for 的优先级比 v-if 更高,这意味着 v-if 将分别重复运行于每个 v-for 循环中。当你只想为部分项渲染节点时,这种优先级的机制会十分有用,如下:
<div id="app8">
<!-- 运行于每个todo循环中, 只渲染存在todo.isComplete的部分节点,即已完成的todo事项 -->
<li v-for="todo in todos" v-if="todo.isComplete">
{{todo}}
</li>
</div>
<script>
var vm8 = new Vue({
el: '#app8',
data: {
todos: [
{
work: 'Math',
isComplete: ''
},
{
work: 'English',
isComplete: 'finish'
},
{
work: 'Chinese',
isComplete: 'finish'
}
]
}
})
</script>
7.8.2使用在不同元素上
而如果你的目的是有条件地跳过循环的执行,那么可以将 v-if 置于外层元素 (或 ) 上。如:
<div id="app9">
<!-- v-if在外层元素判断数据是否存在 -->
<ul v-if="lists.length">
<!-- 数据存在,调用v-for循环渲染 -->
<li v-for="list in lists">{{list.name}}</li>
</ul>
<!-- 数据不存在显示提示语 -->
<p v-else>there is no list</p>
</div>
<script>
var vm9 = new Vue({
el: '#app9',
data: {
lists: [
{
name: 'Bush'
},
{
name: 'Obama'
},
{
name: 'Trump'
}
]
}
})
</script>
7.9 在组件上使用 v-for
<div id="app10">
<my-component v-for="item in items" v-bind:key="item.id" v-bind:item="item"></my-component>
</div>
<script>
// 然而,任何数据都不会被自动传递到组件里,因为组件有自己独立的作用域。
// 为了把迭代数据传递到组件里,我们要使用 prop:
Vue.component('my-component', {
props: ['item'],
template: `<li>{{item.id}}--{{item.name}}--{{item.price}}</li>`
})
var vm10 = new Vue({
el: '#app10',
data: {
items: [
{
id: 1,
name: 'meat',
price: '¥11'
},
{
id: 2,
name: 'fruit',
price: '¥3'
},
{
id: 3,
name: 'vegetables',
price: '¥1'
}
]
}
})
</script>
<!-- 案例:todo-list -->
<div id="todo-list">
<!-- 1)将提交表单和添加事项按钮合并
2)prevent修饰符防止触发默认行为,例如提交表单 -->
<form v-on:submit.prevent="addBtn">
<label for="addTodo">Add a todo item</label>
<input type="text" v-model="textVal" id="new-todo" placeholder="please enter a item">
<button>Add</button>
</form>
<ul v-for="(list , index) in lists">
<li
is="my-component"
:key="list.id"
:content="list.content"
@remove="lists.splice(index, 1)"></li>
</ul>
</div>
<script>
Vue.component('my-component', {
props: ['content'],
template: `\
<li>\
{{ content }}\
<button v-on:click="$emit(\'remove\')">Remove</button>\
</li>\
`
})
var todoList = new Vue({
el: '#todo-list',
data: {
textVal: ' ',
lists: [
],
nextId: 0
},
methods: {
addBtn: function () {
this.lists.push({
id: this.nextId++,
content: this.textVal
});
this.textVal = '';
console.log(this.nextId);
}
}
})
</script>