中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何解析Vue3的響應式原理

發布時間:2021-12-15 16:29:33 來源:億速云 閱讀:188 作者:柒染 欄目:開發技術

本篇文章給大家分享的是有關如何解析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 = newVal
            notifyUpdate()
          }
        }
      })
    }
    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/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的響應式原理,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    vue
    AI

    武邑县| 上饶市| 睢宁县| 寿阳县| 格尔木市| 盐津县| 靖安县| 嵊州市| 陕西省| 林口县| 赣州市| 江口县| 白沙| 太仓市| 兴国县| 从化市| 潜江市| 思南县| 丁青县| 西畴县| 德钦县| 陇南市| 会东县| 临高县| 封开县| 分宜县| 东辽县| 葵青区| 深圳市| 和平区| 黔西县| 安庆市| 垫江县| 鸡东县| 襄城县| 定襄县| 夹江县| 漾濞| 白山市| 衡东县| 巴塘县|