<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> vue3兼容性只到ie11,如果监测到vue3无法兼容,会自动优雅降级到vue2 <script> // vue3中的响应式原理,利用Proxy对象对数据拦截 // 如何避免重复代理 const toProxy = new WeakMap() //形如 obj:observed const toRow = new WeakMap() //形如 observed:obj function isObject(obj){ return typeof obj === 'object' || obj === null } function reactive(obj){ if(!isObject(obj)){ return } // 查找缓存 if(toProxy.has(obj)){ return toProxy.get(obj) } // 传入的obj就是代理对象,此时不用反复代理 if(toRow.has(obj)){ return obj } const observed = new Proxy(obj,{ // 属性的增删改查都涉及到了 get(target,key,receiver){ // 优雅的获取值 const res = Reflect.get(target,key,receiver) console.log(`获取${key}:${res}`); // 运行时递归,相比于初始化递归,性能较好 return isObject(res) ? reactive(res) : res }, set(target,key,val,receiver){ // 返回bool const res = Reflect.set(target,key,val,receiver) console.log(`设置${key}:${res}`); return res }, deleteProperty(target,key){ const res = Reflect.deleteProperty(target,key) console.log(`删除${key}`); return res }, }) // 缓存 toProxy.set(obj,observed) toRow.set(observed,obj) return observed } const data = {foo:'foo',bar:{a:1},arr:[1,2,3]} const react = reactive(data) // 1获取 // react.foo // 2设置已存在属性 // react.foo = 'fooooooo' // 3设置不存在属性 // react.name = 'zhongwuhuang' // 4嵌套对象设置 react.bar.a = 10 react.bar.a // 操作数组 // react.arr[0] = 10 // react.arr // 时候是否缓存成功 // console.log(react === reactive(data)); </script> </body> </html>