一、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双向绑定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | <!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() 是弱引用,在内存不足的时候垃圾回收机制才会回收,可以作为缓存
总结
以上为个人经验,希望能给大家一个参考