共计 1495 个字符,预计需要花费 4 分钟才能阅读完成。
如果你平时有关注 Vue 的进展的话,可能已经知道了在 Vue3.0 中将会通过 Proxy
来替换原本的 Object.defineProperty
来实现数据响应式。Proxy
是 ES6 中新增的功能,它可以用来自定义对象中的操作。
let p = new Proxy(target, handler)
target
代表需要添加代理的对象,handler
用来自定义对象中的操作,比如可以用来自定义 set
或者 get
函数。
接下来我们通过 Proxy
来实现一个数据响应式:
let onWatch = (obj, setBind, getLogger) => {
let handler = {
get(target, property, receiver) {
getLogger(target, property)
return Reflect.get(target, property, receiver)
},
set(target, property, value, receiver) {
setBind(value, property)
return Reflect.set(target, property, value)
}
}
return new Proxy(obj, handler)
}
let obj = { a: 1 }
let p = onWatch(
obj,
(v, property) => {
console.log(` 监听到属性 ${property} 改变为${v}`)
},
(target, property) => {
console.log(`'${property}' = ${target[property]}`)
}
)
p.a = 2 // 监听到属性 a 改变
p.a // 'a' = 2
在上述代码中,我们通过自定义 set
和 get
函数的方式,在原本的逻辑中插入了我们的函数逻辑,实现了在对对象任何属性进行读写时发出通知。
当然这是简单版的响应式实现,如果需要实现一个 Vue 中的响应式,需要我们在 get
中收集依赖,在 set
派发更新,之所以 Vue3.0 要使用 Proxy
替换原本的 API 原因在于 Proxy
无需一层层递归为每个属性添加代理,一次即可完成以上操作,性能上更好,并且原本的实现有一些数据更新不能监听到,但是 Proxy
可以完美监听到任何方式的数据改变,唯一缺陷可能就是浏览器的兼容性不好了。
另外看下 Proxy 的其它用法
const www = new Proxy(new URL('https://www'), {
get: function get(target, prop) {
let o = Reflect.get(target, prop);
if (typeof o === 'function') {
return o.bind(target)
}
if (typeof prop !== 'string') {
return o;
}
if (prop === 'then') {
return Promise.prototype.then.bind(fetch(target));
}
target = new URL(target);
target.hostname += `.${prop}`;
return new Proxy(target, { get });
}
});
访问百度
www.baidu.com.then(response => {
console.log(response.status);
// ==> 200
})
使用 async
/await
语法:
const response = await www.baidu.com
console.log(response.ok)
// ==> true
console.log(response.status);
// ==> 200
正文完