Vue数据双向绑定的原理是在vue实例初始化时递归的给所有的对象属性绑定getter/setter方法,这样导致了两个问题:
- 数组的更新,数组的每一项不是对象
<div id="app">
<p v-for="(item,index) in arr" :key="index">{{item}}</p>
</div>
let vm = new Vue({
el: '#app',
data: {
arr: ['a','b','c','d']
}
})
vm.arr[1] = 'AAA' // 页面不会更新
vm.arr[4] = 'e' // 页面不会更新
- vue数据双向绑定不会递归的给数组的每一项绑定get/set,所以在vue中数组通过下标添加或者修改值的时候不会引起页面更新
- 注意:
Vue 数组中的 push() pop() shift() unshift() splice() sort()reverse()方法,都被进行了包裹二次封装(不是原生js方法),调用这些方法后,相当于内置给数组子项添加set,get方法.所以调用上面的方法将会触发视图更新
可以引起数组更新视图的方法有三种:
方法一: 调用上面说的数组中的方法
方法二: 使用新数组替换旧数组
方法三: 使用vm.$set 或者Vue.set方法修改数组指定下标的值
用法: vm.$set(数组,index,val) / Vue.set(数组,index,value)
let vm = new Vue({
el: '#app',
data: {
arr: ['a','b','c','d']
}
})
vm.$set(vm.arr,0,"aaa") // 页面更新
Vue.set(vm.arr,0,"aaa") // 页面更新
vm.arr.push("aaa") // 页面更新
vm.arr = vm.arr.map((item)=>item) // 页面更新
- 对象的更新,因为在Vue初始化时对象中的所有属性都被添加了get/set,所以对象可以直接通过属性名修改就会引起页面的更细,但是如果在Vue实例化之后给某个对象添加新的属性,这个属性将不包含get/set方法。就不会引起页面更新。给对象添加新属性引起页面更新的方法 : 一 新对象替换旧对象
<div id="app">
<p v-for="(val,key) in obj" :key="key">{{val}}</p>
</div>
vm.$set(vm.obj, 'address', '深圳') // 页面会更新
vm.$set(vm.obj, 'address', '广州') // 页面会更新
vm.obj.address = '佛山' //address 自动添加get set 页面会更新
Vue.set(vm.obj, 'hobby', '吃肉') // 页面会更新
可以引起对象更新视图的方法有三种:
- 旧对象可直接赋值
- 通过vm.$ set建立新键值对
用法: vm.$set(数组,index,val) / Vue.set(数组,index,value)