Vue3的响应式原理解析
生活随笔
收集整理的這篇文章主要介紹了
Vue3的响应式原理解析
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Vue3的響應式原理解析
Vue2響應式原理回顧
// 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 = newValnotifyUpdate()}}}) } function notifyUpdate () {console.log('頁面更新!') }vue2響應式弊端:
響應化過程需要遞歸遍歷,消耗較大
新加或刪除屬性無法監聽
數組響應化需要額外實現
Map、Set、Class等無法響應式
修改語法有限制
Vue3響應式原理剖析
vue3使用ES6的Proxy特性來解決這些問題。
function reactive (obj) {if (typeof obj !== 'object' && obj != null) {return obj}// Proxy相當于在對象外層加攔截// http://es6.ruanyifeng.com/#docs/proxyconst observed = new Proxy(obj, {get (target, key, receiver) {// Reflect用于執行對象默認操作,更規范、更友好// Proxy和Object的方法Reflect都有對應// http://es6.ruanyifeng.com/#docs/reflectconst 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:observedconst toRaw = new WeakMap() // 形如observed:objfunction 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)?原創不易,還希望各位大佬支持一下\textcolor{blue}{原創不易,還希望各位大佬支持一下}原創不易,還希望各位大佬支持一下
👍 點贊,你的認可是我創作的動力!\textcolor{green}{點贊,你的認可是我創作的動力!}點贊,你的認可是我創作的動力!
?? 收藏,你的青睞是我努力的方向!\textcolor{green}{收藏,你的青睞是我努力的方向!}收藏,你的青睞是我努力的方向!
?? 評論,你的意見是我進步的財富!\textcolor{green}{評論,你的意見是我進步的財富!}評論,你的意見是我進步的財富!
總結
以上是生活随笔為你收集整理的Vue3的响应式原理解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows下干不过 AMD悄然在Li
- 下一篇: react Native 环境安装配置—