vue3双向绑定实现原理解读
作者:这是提莫大人
这篇文章主要介绍了vue3双向绑定实现原理解读,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
一、vue3为什么要用proxy实现双向绑定?
1.object.defineProperty的缺点
因为es5的object.defineProperty无法监听对象属性的删除和添加
不能监听数组的变化,除了push/pop/shift/unshift/splice/spObject.definert/reverse,其他都不行
Object.defineProperty只能遍历对象属性直接修改(需要深拷贝进行修改)
2.proxy的优点
>1、直接监听对象而非属性
>2、直接监听数组的变化
>3、拦截的方式有很多种(有13种,set,get,has)
>4、Proxy返回一个新对象,可以操作新对象达到目的
3.proxy的缺点
1、proxy有兼容性问题
不能用polyfill来兼容(polyfill主要抚平不同浏览器之间对js实现的差异)
二、实现Vue3双向绑定
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div></div> <script> const toProxy = new WeakMap(); //存放的是代理后的对象 const toRaw = new WeakMap(); //存放的是代理前的对象 function trigger() { console.log('触发视图更新') } function isObject(target) { return typeof target === 'object' && target !== null; } function reactive(target) { if (!isObject(target)) { return target; } let proxy = toProxy.get(target) // 如果代理表中已经存在了 就把这个结果返回 if (proxy) { return proxy } // 如果这个对象已经被代理过了 就直接返回 if (toRaw.has(target)) { return target; } const handlers = { set(target, key, value, receiver) { if (target.hasOwnProperty(key)) { trigger() } return Reflect.set(target, key, value, receiver) }, get(target, key, value, receiver) { const res = Reflect.get(target, key, receiver) if (isObject(target[key])) { return reactive(res) } return res; }, deleteProperty(target, key) { return Reflect.deleteProperty(target, key) } } let observed = new Proxy(target, handlers) toProxy.set(target, observed); toRaw.set(observed, target) return observed } let obj = { name: '温小鹿', arr: [1, 2, 3] } // let p = reactive(obj) // p.name = 'jw' // let arr = [1, 2 ,3]; // let p = reactive(arr) // p.push(4); // console.log(p) let p = reactive(obj) p = reactive(p) p = reactive(p) p.arr.push(4) console.log(p) </script> </body> </html>
害,基础不扎实,复习一下
Reflect是ES6为操作对象而提供的新API,proxy对象的方法在rReflect上都能找到
new WeakMap() 是弱引用,在内存不足的时候垃圾回收机制才会回收,可以作为缓存
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。