数据响应式原理
Vue 的数据响应式原理是基于 JavaScript 的 Object.defineProperty()
方法实现的。该方法可以将一个对象的属性转化为 getter 和 setter,从而在访问或修改该属性时触发相应的回调函数。在 Vue 中,每个组件都有一个对应的“响应式系统”,用于监听组件的数据变化并更新相关的视图。
当我们在 Vue 中声明一个数据对象时,Vue 会遍历该对象的每个属性,并使用 Object.defineProperty()
方法将其转化为 getter 和 setter。这样,当我们访问或修改该属性时,就会触发相应的回调函数,并通知 Vue 去更新相关的组件
修改数组时的一个问题和解决方法
this.personList[0] = { id: 1, name: 'aaaaaaaaaa', age: 18 } 更改data数据,Vue不监听,模板不改变
<div id="app">
<h2>学校:{{schoolName}}</h2>
<ul>
<li v-for="(p, index) of personList" :key="index">
{{ p.name }}-{{ p.age }}
</li>
</ul>
<button @click="updatePerson">修改第一行姓名</button>
</div>
<script>
let vm = new Vue({
el: '#app',
data: {
schoolName: '北京大学',
personList: [
{ id: 1, name: '张三', age: 18 },
{ id: 2, name: '李四', age: 19 }
]
},
methods: {
//编辑数组 https://v2.cn.vuejs.org/v2/guide/list.html#变更方法
updatePerson() {
//***********可行的方式***********
// this.personList[0].name = 'aaa';//修改属性,可以触发视图更新 vm有get,set
// Vue.set(this.personList, 0, { id: 1, name: 'aaaaaaaaaa', age: 18 })
// this.$set(this.personList, 0, { id: 1, name: 'aaaaaaaaaa', age: 18 })
this.personList.splice(0, 1, { id: 1, name: 'aaaaaaaaaa', age: 18 })//通过删除或替换现有元素和/或添加新元素来更改数组的内容。
//***********不可行的方式***********
// this.personList[0] = { id: 1, name: 'aaaaaaaaaa', age: 18 };//修改对象,没有触发视图更新
}
},
})
</script>
总结
- vue会监视data中所有层次的数据
- 通过setter实现监视,且要在new Vue()时就传入要监测的数据(data)
- 对象创建后追加的属性,Vue默认不做响应式处理
- 如需后面添加的属性做响应式,请使用如下API:
Vue.set(target, propertyName/index, value) vm.$set(target, propertyName/index, value)
- 数组监测更新方式: 通过包裹数组更新元素的方法实现:
- (1)调用原生对应的方法对数组进行更新
- (2)重新解析模板,进而更新页面
- 数组变更方法
push() 、pop() 、unshift() 、shift() 、splice() 、sort()、 reverse() Vue.set()或vm.$set()
特别注意:Vue.set() 和 vm.$set() 不能给vm或vm的根数据对象(data等)添加属性