Proxy 与Object.defineProperty 实现响应式的区别
程序员文章站
2022-07-12 21:54:42
...
Object.defineProperty 劫持数据
- 只是对对象的属性进行劫持
- 无法监听新增属性和删除属性,需要使用 vue.set, vue.delete
- 深层对象的劫持需要一次性递归
- 劫持数组时需要重写覆盖部分 Array.prototype 原生方法,[‘push’, ‘pop’, ‘shift’, ‘unshift’, ‘splice’, ‘sort’, ‘reverse’] 会改变原数组的原生方法不会被 Object.defineProperty 劫持,需要重新写数组的原生方法添加更新触发
Object.defineProperty 实现响应式
function defineReactive(target, key, value) {
observer(value) // 对 value 深层监听
Object.defineProperties(target, key, {
get() {
// dep.addSubs(watcher) // 添加到监听队列
return value
},
set(newValue) {
if (newValue !== value) {
observer(newValue) // 再次劫持新 value
value = newValue
// dep.notify() // 通知依赖触发监听队列的更新
}
}
})
}
function observer(target) {
if (typeof target !== 'object' || !target) {
return target
}
if (Array.isArray(target)) {
target.__proto__ = newArrProto
}
for (let key of target) {
defineReactive(target, key, target[key])
}
}
const oldArrProto = Array.prototype
const newArrProto = Object.create(oldArrProto)
['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(methodName => {
newArrProto[methodName] = function(...args) {
// dep.notify()
oldArrProto[methodName].apply(this, args)
}
})
Proxy 劫持数据
- 可以监听到对象新增删除属性
- 只在 getter 时才对对象的下一层进行劫持(优化了性能)
- 能正确监听原生数组方法
- 无法 polyfill 存在浏览器兼容问题,IE不支持,Edge12支持
详细了解 Proxy
Proxy 实现响应式
function reactive(target = {}) {
if (typeof target !== 'object' || target == null) {
return target
}
const proxyConfig = {
get(target, key, receiver) {
const ownKeys = Reflect.ownKeys(target)
if (ownKeys.includes(key)) {
// dep.subs(watcher) // 添加监听
}
const result = Reflect.get(target, key, receiver)
return reactive(result) // 只在 getter 时才再次劫持
},
set(target, key, val, receiver) {
if (val === target[key]) {
return
}
const ownKeys = Reflect.ownKeys(target)
if (ownKeys.includes(key)) {
// 已有值
} else {
// 新增值
}
const result = Reflect.set(target, key, val, receiver)
// dep.noitfy() // 通知监听队列进行更新
return result
},
deleteProperty(target, key) {
const result = Reflect.deleteProperty(target, key)
return result
}
}
const observed = new Proxy(target, proxyConfig)
return observed
}
推荐阅读
-
利用Object.defineProperty简单实现vue的数据响应式原理
-
vue3.0响应式数据是如何实现的?相比vue2.0中Object.defineProperty()有什么优势?
-
浅谈Object.defineProperty与Proxy的区别
-
Proxy 与Object.defineProperty 实现响应式的区别
-
Vue 中 Object.defineProperty 与 Proxy 实现双向绑定的原理
-
自适应和响应式布局的区别,em与rem
-
Vue3 的响应式和以前有什么区别,Proxy 无敌?
-
自适应和响应式布局的区别,em与rem
-
Vue3 的响应式和以前有什么区别,Proxy 无敌?
-
vue2.x与vue3.0_proxy与Object.defineProperty()的区别