您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關如何解析Vue3的響應式原理,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
// 1.對象響應化:遍歷每個key,定義getter、setter // 2.數組響應化:覆蓋數組原型方法,額外增加通知邏輯 const originalProto = Array.prototype const arrayProto = Object.create(originalProto) ;['push', 'pop', 'shift', 'unshift', 'splice', 'reverse', 'sort'].forEach( method => { arrayProto[method] = function () { originalProto[method].apply(this, arguments) notifyUpdate() } } ) function observe (obj) { if (typeof obj !== 'object' || obj == null) { return } // 增加數組類型判斷,若是數組則覆蓋其原型 if (Array.isArray(obj)) { Object.setPrototypeOf(obj, arrayProto) } else { const keys = Object.keys(obj) for (let i = 0; i < keys.length; i++) { const key = keys[i] defineReactive(obj, key, obj[key]) } } } function defineReactive (obj, key, val) { observe(val) // 解決嵌套對象問題 Object.defineProperty(obj, key, { get () { return val }, set (newVal) { if (newVal !== val) { observe(newVal) // 新值是對象的情況 val = newVal notifyUpdate() } } }) } function notifyUpdate () { console.log('頁面更新!') }
vue2響應式弊端:
響應化過程需要遞歸遍歷,消耗較大
新加或刪除屬性無法監聽
數組響應化需要額外實現
Map、Set、Class等無法響應式
修改語法有限制
vue3使用ES6的Proxy特性來解決這些問題。
function reactive (obj) { if (typeof obj !== 'object' && obj != null) { return obj } // Proxy相當于在對象外層加攔截 // http://es6.ruanyifeng.com/#docs/proxy const observed = new Proxy(obj, { get (target, key, receiver) { // Reflect用于執行對象默認操作,更規范、更友好 // Proxy和Object的方法Reflect都有對應 // http://es6.ruanyifeng.com/#docs/reflect const res = Reflect.get(target, key, receiver) console.log(`獲取${key}:${res}`) return res }, set (target, key, value, receiver) { const res = Reflect.set(target, key, value, receiver) console.log(`設置${key}:${value}`) return res }, deleteProperty (target, key) { const res = Reflect.deleteProperty(target, key) console.log(`刪除${key}:${res}`) return res } }) return observed } //代碼測試 const state = reactive({ foo: 'foo', bar: { a: 1 } }) // 1.獲取 state.foo // ok // 2.設置已存在屬性 state.foo = 'fooooooo' // ok // 3.設置不存在屬性 state.dong = 'dong' // ok // 4.刪除屬性 delete state.dong // ok
測試:嵌套對象不能響應
// 設置嵌套對象屬性 react.bar.a = 10 // no ok
添加對象類型遞歸
// 提取幫助方法 const isObject = val => val !== null && typeof val === 'object' function reactive (obj) { //判斷是否對象 if (!isObject(obj)) { return obj } const observed = new Proxy(obj, { get (target, key, receiver) { // ... // 如果是對象需要遞歸 return isObject(res) ? reactive(res) : res }, //... }
重復代理,比如
reactive(data) // 已代理過的純對象
reactive(react) // 代理對象
解決方式:將之前代理結果緩存,get時直接使用
const toProxy = new WeakMap() // 形如obj:observed const toRaw = new WeakMap() // 形如observed:obj function reactive (obj) { //... // 查找緩存,避免重復代理 if (toProxy.has(obj)) { return toProxy.get(obj) } if (toRaw.has(obj)) { return obj } const observed = new Proxy(...) // 緩存代理結果 toProxy.set(obj, observed) toRaw.set(observed, obj) return observed } // 測試效果 console.log(reactive(data) === state) console.log(reactive(state) === state)
以上就是如何解析Vue3的響應式原理,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。