Open shizhihuaxu opened 3 years ago
把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter,做依赖收集和派发更新;每个组件实例都对应一个 Watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染;
初始化数据时会层层判断 data,props property 对应的 value 是不是对象(一个数组或者纯对象),如果是的话需要将 value 的属性也处理为响应式属性;这里会有两种情况:
一、如果 value 是一个纯对象的话,直接将此对象的 property 转为 getter/setter;
二、如果 value 是一个数组的话,是对数组的每个元素进行处理,并没有将数组索引定义为响应式属性(因此利用索引直接设置一个数组项不会触发视图的更新)元素不是对象则不做处理,若每个元素为对象,则将元素每个属性定义为响应式属性;
初始化实例时属性未定义在 data 选项中
var vm = new Vue({
data:{
a:1
}
})
vm.a // 响应式
vm.b // 初始化后再添加直接属性,非响应式
解决方案:
Vue.set ,this.$set
对象新增、删除属性
<div>{{ obj.age }}</div>
<div>{{ obj.name }}</div>
data() {
return {
obj: {
age: 32
}
}
}
change() {
delete this.obj.age // 删除属性
connsole.log(this.obj.age) // undefined
this.obj.name = 'lisi' // 新增属性
connsole.log(this.obj.name) // lisi
}
解决方案:直设置整个对象的值
this.obj = {
name: 'lisi'
}
利用索引直接设置一个数组项
<div>{{ arr1[1] }}</div>
<div>{{ arr2[0].age }}</div>
data() {
return {
arr1: [1,2,3], // 数组情况1
arr2: [ // 数组情况 2
{
age: 12,
},
{
age: 11,
},
],
}
}
change() {
this.arr1[1] = 777 // 示例 1
this.arr2[0] = { // 示例 2
age: 442
}
}
解决方案:
1、Vue.set ,this.$set
2、借助数组操作方法
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
3、this.arr2[0].age = 442
直接修改数组的长度
<div>{{ arr.length }}</div> // 3
data() {
return {
arr: [1,2,3]
}
}
change() {
this.arr.length = 888
}
解决方案:
借助数组方法:
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
vue 基于原生Array的原型对象创建了一个新对象,重新定义了数组中的以下方法,将以上方法定义通过defineProperty 定义成了响应式,参见 core/observer/array。
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
1、vue 是如何实现响应式的?(数据变化触发视图更新) 2、哪些情况下不能在数据变化后触发视图更新?为什么? 3、如何解决上述问题 2 ,原理又是什么? 4、为什么数组push 、shift 等一些操作可以触发视图更新?