提示:本博客用于分享本人学习心得,如有错误之处欢迎大家指出。
前言
在上一篇文章vue2 响应式之Object.defineProperty中,我们知道了vue2是通过Object.defineProperty这个API来实现响应式的。 那么, 为什么vue3要使用proxy来替代Object.defineProperty? 就像上一篇中讲到的,vue2.x基于Object.defineProperty的实现,存在很多缺点:一次性递归计算量大、无法新增/删除属性、对于数组的监听需要特殊处理,而proxy可以消除这些限制。
什么是proxy?
MDN上是这么描述的–proxy用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。 官方的解释总是言简意赅、以至于不明觉厉… 简单来说,proxy就是给目标对象虚拟化一个代理对象,这样我们可以不直接操作对象本身,而是通过操作对象的代理对象来间接来操作对象,达到预期的目的~
如果还是不清除的话,我们来看下面这个例子
let target = {};
let p = new Proxy(target, {});
p.a = 37;
console.log(target.a);
上面列子中,我们先定义一个对象target,通过proxy生成一个对象p,然后对p进行操作,代理会将所有应用到p上的的操作转发到target上。
proxy监听数据?
1、测试代码如下
function proxyReactive(target) {
if (typeof target !== 'object' || target === null) {
return target
}
const proxyConfig = {
get(target, key, recevier) {
const ownKeys = Reflect.ownKeys(target)
if (ownKeys.includes(key)) {
}
const result = Reflect.get(target, key, recevier)
return proxyReactive(result)
},
set(target, key, val, recevier) {
if (val === target[key]) {
return true
}
const ownKeys = Reflect.ownKeys(target)
if (ownKeys.includes(key)) {
console.log('原有的')
} else {
console.log('新增的')
}
const result = Reflect.set(target, key, val, recevier)
return result
},
deleteProperty(target, key, recevier) {
const result = Reflect.deleteProperty(target, key, recevier)
return result
}
}
const observeProxy = new Proxy(target, proxyConfig)
return observeProxy
}
const data = {
name: 'jl',
age: 13,
a: [1, 2, 3, 4]
}
const proxyData = proxyReactive(data)
2、Object.defineProperty和Proxy对比
(1)获取数据
function defineReactive(target, key, value) {
...
Object.defineProperty(target, key, {
get() {
return value
}
...
}
function proxyReactive(target) {
...
const proxyConfig = {
get(target, key, recevier) {
const ownKeys = Reflect.ownKeys(target)
if (ownKeys.includes(key)) {
}
const result = Reflect.get(target, key, recevier)
return proxyReactive(result)
}
...
}
const observeProxy = new Proxy(target, proxyConfig)
...
}
(2)设置数据
function defineReactive(target, key, value) {
...
Object.defineProperty(target, key, {
...
set(newValue) {
if (newValue !== value) {
value = newValue
}
}
...
}
function proxyReactive(target) {
...
const proxyConfig = {
...
set(target, key, val, recevier) {
if (val === target[key]) {
return true
}
const ownKeys = Reflect.ownKeys(target)
if (ownKeys.includes(key)) {
console.log('原有的')
} else {
console.log('新增的')
}
const result = Reflect.set(target, key, val, recevier)
return result
}
...
}
const observeProxy = new Proxy(target, proxyConfig)
...
}
(3)深度监听
function defineReactive(target, key, value) {
observe(value)
...
}
function proxyReactive(target) {
...
const proxyConfig = {
...
get(target, key, recevier) {
const ownKeys = Reflect.ownKeys(target)
if (ownKeys.includes(key)) {
}
const result = Reflect.get(target, key, recevier)
return proxyReactive(result)
}
...
}
const observeProxy = new Proxy(target, proxyConfig)
...
}
object.defineProperty深度监听是一次性递归,计算量大 Proxy深度监听是获取到那一级就监听到那一级
总结
- Proxy能够规避Object.defineProperty的问题
- Proxy无法监听所有浏览器,无法polyfill
相关文章:
vue2 响应式之Object.defineProperty
|