<!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>