Vue响应式原理
Vue响应原理的核心是数据劫持和依赖收集,主要是利用Object.defineProperty() 实现对数据存取操作的拦截,我们把这个实现称为数据代理;同时我们通过对数据get方法的拦截,可以获取到对数据的依赖,并将出所有的依赖收集到一个集合中
?疑惑
1:Object.defineProperty()怎么 实现对数据存取操作的拦截?
2:依赖是什么?
回顾Object.defineProperty()
语法
Object.define.property(obj, prop, descriptor)
obj:要定义属性的对象 ?prpo:定义或修改属性的名称 ?descriptor:要定义或修改睡醒的修饰符
configurable 当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。 默认为 false。
enumerable 当且仅当该属性的 enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中。 默认为 false。
数据描述符还具有以下可选键值:
value 该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。 默认为 undefined。
writable 当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符 (en-US)改变。 默认为 false。
存取描述符还具有以下可选键值:
get 属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。 默认为 undefined。
set 属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。 默认为 undefined。
const obj={}
Object.defineProperty(obj, 'name', {
configurable: true, //表示是否通过delete删除属性从而重新定义属性, 能否修改属性的特性, 或者能否把属性修改为访问器属性(属性直接定义在对象中, 默认为true)。 当为false时, 不能重新定义不能使用delete删除。
enumerable: true, // ? 表示能否通过for - in循环返回属性。
writable: true, // ? 表示能否修改属性的值。
value: 'terry' // ? 包含这个属性的数据值
})
console.log(obj.name);//terry
以上就是Object的用法
数据劫持
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
//拦截get,当我们访问data.key时会被这个方法拦截到
get: function getter () {
//我们在这里收集依赖
return obj[key];
},
//拦截set,当我们为data.key赋值时会被这个方法拦截到
set: function setter (newVal) {
//当数据变更时,通知依赖项变更UI
}
})
我们通过Object.defineProperty 为对象obj 添加属性,可以设置对象属性的getter 和setter 函数。之后我们每次通过点语法获取属性都会执行这里的getter 函数,在这个函数中我们会把调用此属性的依赖收集到一个集合中 ;而在我们给属性赋值(修改属性)时,会触发这里定义的setter 函数,在次函数中会去通知集合中的依赖更新,做到数据变更驱动视图变更。
那什么是依赖 ?
Vue响应式原理-理解Observer、Dep、Watcher
Vue 响应式原理的核心就是Observer 、Dep 、Watcher ,三者共同构成 MVVM 中的 VM
Observer 中进行数据响应式处理以及最终的Watcher 和Dep 关系绑定,在数据被读的时候,触发get 方法,将 Watcher 收集到 Dep 中作为依赖;在数据被修改的时候,触发set 方法,Dep 就遍历 subs 中的订阅者,通知Watcher 更新
Watcher ?作为连接?Observer ?和?Compile ?之间的桥梁,能够订阅并且收到每个属性变动的通知,执行绑定的相应的回调函数,从而更新视图。
|