Vue 中 Object.defineProperty 与 Proxy 实现双向绑定的原理
程序员文章站
2022-07-12 21:54:36
...
实现双向绑定的三要素
- 响应式: 如何监听数据变化
- 模板引擎: 如何解析HTML代码
- 渲染: 如何将监听到的数据变化和解析后的HTML进行渲染
一、Object.defineProperty
通过 Object.defineProperty
监听对象属性的改变
实例定义的属性,vue 内部通过
Object.defineProperty
重新定义,生成 Observer
// 实例定义的属性
const obj = {
message: '哈哈哈',
name: 'jack'
}
// vue 内部流程
Object.keys(obj).forEach(key => {
let value = obj[key]
Object.defineProperty(obj, key, {
set(newValue) {
// 监听 key 的改变
value = newValue
},
get() {
// 获取 key 对应的值
return value
}
})
})
当数据发生改变时,vue是如何知道?
-
利用
Object.defineProperty
生成的Observer
针对对象的属性进行"劫持",一个属性创建一个Dep
对象,在属性发生变化后通知订阅者 -
解析器(Compile)解析模板中的 Directive(指令),获取到哪里用到了属性(订阅者),比如
{{name}} {{message}}
,创建一个观察者watcher
添加到对应的Dep
对象中,同时初始化view
,在界面上显示 -
Watcher
属于Observer
和Compile
桥梁,将接收到的Observer
产生的数据变化,并根据Compile
提供的指令进行视图渲染,使得数据变化促使视图变化
Object.defineProperty的缺陷
-
无法监听数组变化
只有以下七种方法可以检测到数组变化push() pop() shift() unshift() splice() sort() reverse()
-
只能劫持对象的属性,因此需要对对象的每个属性进行遍历,如果属性值也是对象那么需要深度遍历,显然能劫持一个完整的对象是更好的选择
二、Proxy
var model = {}
var p = new Proxy(model, {
get(model, prop) {
return model[prop]
},
set(model, prop, value) {
model[prop] = value
// 当 model 中的数据发生改变时, view 中的数据也自动改变
document.querySelector('[v-bind]').innerHTML = value
}
})
// 当 view 中的数据发生改变时, model 中的数据自动改变
document.querySelector('[v-model]').oninput = function (e) {
p.msg = e.target.value
}
Proxy 的优点
- 可以直接监听对象而非属性
- 可以直接监听数组的变化
- 返回的是一个新对象,可以只操作新的对象达到目的,而
Object.defineProperty
只能遍历对象属性直接修改
推荐阅读
-
vue使用Proxy实现双向绑定的方法示例
-
深入理解vue.js双向绑定的实现原理
-
Angular和Vue双向数据绑定的实现原理(重点是vue的双向绑定)
-
vue中的双向数据绑定原理与常见操作技巧详解
-
Vue 的双向绑定原理与用法揭秘
-
自定义Vue中的v-module双向绑定的实现
-
浅谈vue中数据双向绑定的实现原理
-
使用 Object.defineProperty (vue2)和 Proxy(vue3)实现Vue双向数据绑定
-
分别使用 Object.defineProperty 和 proxy 实现简单的数据双向绑定
-
用object.defineproperty()和proxy实现简单的双向绑定,并比较两者优劣