我们可以用 v-for 指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>v-for遍历对象</title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<!--
vue包含观察数组的变异方法,他们将会触发视图更新
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
调用原生,更新界面(让数组的内部改变有了数据绑定)
-->
</head>
<body>
<div id="demo">
<h2>测试:v-for遍历数组</h2>
<ul>
<li v-for="(p,index) in persons" :key="index">
{{index}}---{{p.name}}---{{p.age}}
---<button type="button" @click="deleteP(index)">删除</button>
--<button type="button" @click="update(index,{name:'baby',age:12})">更新</button>
</li>
</ul>
<h2>测试:v-for遍历对象</h2>
<ul>
<li v-for="(value,key) in persons[1]" >
{{key}}-----{{value}}
</li>
</ul>
</div>
<script type="text/javascript">
/*vue本身是监视了persons的改变,没有监视数组内部数据的改变
vue重写了数组中的一系列改变数组内部数据的方法(先调用原生,更新界面)-->数组内部改变,界面自动变化
*/
new Vue({
el:'#demo',
data:{
persons:[//Vue只是监视了persons的改变,没有监视数组内部数据的改变
{name: 'tom', age: 18},
{name: 'jack', age: 20},
{name: 'bob', age: 30}
]
},
methods:{
deleteP(index){
//删除persons中指定的index的ip
this.persons.splice(index,1); //参数第一个是元素的位置
},
update(index, newP){
//this.persons[index] = newP ;//改变的是数组内部,并没有改变persons本身,没有调用变异方法,vue不会更新界面
this.persons.splice(index,1,newP);
}
}
})
</script>
</body>
</html>

维护状态
当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。这个类似 Vue 1.x 的 track-by="$index"。
这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性:
因为它是 Vue 识别节点的一个通用机制,key 并不仅与 v-for 特别关联。后面我们将在指南中看到,它还具有其它用途。
不要使用对象或数组之类的非基本类型值作为 v-for 的 key。请用字符串或数值类型的值。
数组更新检测
变异方法 (mutation method)
Vue 将被侦听的数组的变异方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
替换数组
变异方法,顾名思义,会改变调用了这些方法的原始数组。相比之下,也有非变异 (non-mutating method) 方法,例如 filter()、concat() 和 slice() 。它们不会改变原始数组,而总是返回一个新数组。当使用非变异方法时,可以用新数组替换旧数组:
example1.items = example1.items.filter(function (item) {
return item.message.match(/Foo/)
})
你可能认为这将导致 Vue 丢弃现有 DOM 并重新渲染整个列表。幸运的是,事实并非如此。Vue 为了使得 DOM 元素得到最大范围的重用而实现了一些智能的启发式方法,所以用一个含有相同元素的数组去替换原来的数组是非常高效的操作。
注意事项:
由于 JavaScript 的限制,Vue 不能检测以下数组的变动:
1当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
2当你修改数组的长度时,例如:vm.items.length = newLength
举个例子:
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
})
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的
为了解决第一类问题,以下两种方式都可以实现和 vm.items[indexOfItem] = newValue 相同的效果,同时也将在响应式系统内触发状态更新:
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
你也可以使用 vm.$set 实例方法,该方法是全局方法 Vue.set 的一个别名:
vm.$set(vm.items, indexOfItem, newValue)
为了解决第二类问题,你可以使用 splice:
vm.items.splice(newLength)
对象变更检测注意事项
还是由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除:
var vm = new Vue({
data: {
a: 1
}
})
// `vm.a` 现在是响应式的
vm.b = 2
// `vm.b` 不是响应式的
对于已经创建的实例,Vue 不允许动态添加根级别的响应式属性。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式属性。例如,对于:
var vm = new Vue({
data: {
userProfile: {
name: 'Anika'
}
}
})
你可以添加一个新的 age 属性到嵌套的 userProfile 对象:
Vue.set(vm.userProfile, 'age', 27)
你还可以使用 vm.$set 实例方法,它只是全局 Vue.set 的别名:
vm.$set(vm.userProfile, 'age', 27)
有时你可能需要为已有对象赋值多个新属性,比如使用 Object.assign() 或 _.extend()。在这种情况下,你应该用两个对象的属性创建一个新的对象。所以,如果你想添加新的响应式属性,不要像这样:
Object.assign(vm.userProfile, {
age: 27,
favoriteColor: 'Vue Green'
})
你应该这样做:
vm.userProfile = Object.assign({}, vm.userProfile, {
age: 27,
favoriteColor: 'Vue Green'
})
730

被折叠的 条评论
为什么被折叠?



