最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Vue3的響應(yīng)式原理解析

 更新時間:2021年12月14日 17:20:30   作者:幾何心涼  
這篇文章主要為大家介紹了Vue3的響應(yīng)式原理解析,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助

Vue2響應(yīng)式原理回顧

// 1.對象響應(yīng)化:遍歷每個key,定義getter、setter
// 2.數(shù)組響應(yīng)化:覆蓋數(shù)組原型方法,額外增加通知邏輯
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
  }
  // 增加數(shù)組類型判斷,若是數(shù)組則覆蓋其原型
  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響應(yīng)式弊端:
響應(yīng)化過程需要遞歸遍歷,消耗較大
新加或刪除屬性無法監(jiān)聽
數(shù)組響應(yīng)化需要額外實現(xiàn)
Map、Set、Class等無法響應(yīng)式
修改語法有限制

Vue3響應(yīng)式原理剖析

vue3使用ES6的Proxy特性來解決這些問題。

function reactive (obj) {
  if (typeof obj !== 'object' && obj != null) {
    return obj
  }
  // Proxy相當(dāng)于在對象外層加攔截
  // http://es6.ruanyifeng.com/#docs/proxy
  const observed = new Proxy(obj, {
    get (target, key, receiver) {
      // Reflect用于執(zhí)行對象默認操作,更規(guī)范、更友好
      // Proxy和Object的方法Reflect都有對應(yīng)
      // 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(`設(shè)置${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.設(shè)置已存在屬性
state.foo = 'fooooooo' // ok
// 3.設(shè)置不存在屬性
state.dong = 'dong' // ok
// 4.刪除屬性
delete state.dong // ok

嵌套對象響應(yīng)式

測試:嵌套對象不能響應(yīng)

// 設(shè)置嵌套對象屬性
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
          },
          //...
        }

避免重復(fù)代理

重復(fù)代理,比如

reactive(data) // 已代理過的純對象
reactive(react) // 代理對象

解決方式:將之前代理結(jié)果緩存,get時直接使用

const toProxy = new WeakMap() // 形如obj:observed
      const toRaw = new WeakMap() // 形如observed:obj
      function reactive (obj) {
        //...
        // 查找緩存,避免重復(fù)代理
        if (toProxy.has(obj)) {
          return toProxy.get(obj)
        }
        if (toRaw.has(obj)) {
          return obj
        }
        const observed = new Proxy(...)
        // 緩存代理結(jié)果
        toProxy.set(obj, observed)
        toRaw.set(observed, obj)
        return observed
      }
      // 測試效果
      console.log(reactive(data) === state)
      console.log(reactive(state) === state)

總結(jié)

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • 深入淺析Vue中的 computed 和 watch

    深入淺析Vue中的 computed 和 watch

    computed 計算屬性是通過屬性計算得來的屬性,watch屬性變化,就會觸發(fā)監(jiān)聽的函數(shù)。下面通過本文給大家介紹Vue中的 computed 和 watch,感興趣的朋友一起看看吧
    2018-06-06
  • vue中data和props的區(qū)別詳解

    vue中data和props的區(qū)別詳解

    這篇文章主要介紹了vue中data和props的區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作有一定的參考學(xué)習(xí)價值,需要的朋友們下面跟著小編來一起學(xué)習(xí)吧
    2024-01-01
  • 前端vue+element使用SM4國密加密解密的詳細實例

    前端vue+element使用SM4國密加密解密的詳細實例

    國密即國家密碼局認定的國產(chǎn)密碼算法,主要有SM1,SM2,SM3,SM4,下面這篇文章主要給大家介紹了關(guān)于前端vue+element使用SM4國密加密解密的相關(guān)資料,需要的朋友可以參考下
    2023-03-03
  • vue2首次加載屏幕閃爍問題

    vue2首次加載屏幕閃爍問題

    這篇文章詳細介紹了Vue.js項目的基本結(jié)構(gòu)和執(zhí)行流程,包括index.html、main.js、App.vue和路由配置的關(guān)系,特別強調(diào)了在index.html中設(shè)置BASE_URL和cdn的使用,以及在main.js中使用render函數(shù)來減少打包體積
    2025-01-01
  • vue3中使用ref語法糖的示例代碼

    vue3中使用ref語法糖的示例代碼

    Vue3提了一個Ref?Sugar的RFC,即ref語法糖,目前還處理實驗性的(Experimental)階段,今天通過本文給大家介紹vue3中使用ref語法糖的相關(guān)知識,感興趣的朋友跟隨小編一起看看吧
    2022-09-09
  • vue基于mint-ui的城市選擇3級聯(lián)動的示例

    vue基于mint-ui的城市選擇3級聯(lián)動的示例

    本篇文章主要介紹了vue基于mint-ui的城市選擇3級聯(lián)動的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • vue使用vue-video-player插件播放視頻的步驟講解

    vue使用vue-video-player插件播放視頻的步驟講解

    在最近的項目中有一個視頻播放的功能,在之前的項目中沒有接觸過類似的功能,第一次接觸,把具體操作步驟一下,這篇文章主要給大家介紹了關(guān)于vue使用vue-video-player插件播放視頻的相關(guān)資料,需要的朋友可以參考下
    2022-12-12
  • 在vant 中使用cell組件 定義圖標該圖片和位置操作

    在vant 中使用cell組件 定義圖標該圖片和位置操作

    這篇文章主要介紹了在vant 中使用cell組件 定義圖標該圖片和位置操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • vue3封裝el-pagination分頁組件的完整代碼

    vue3封裝el-pagination分頁組件的完整代碼

    這篇文章主要介紹了vue3封裝el-pagination分頁組件的完整代碼,本文通過實例代碼給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧
    2024-02-02
  • 為什么vue中不建議使用空字符串作為className

    為什么vue中不建議使用空字符串作為className

    本文主要介紹了為什么vue中不建議使用空字符串作為className,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09

最新評論

十堰市| 宣威市| 松桃| 南康市| 临汾市| 延吉市| 梅河口市| 永宁县| 合肥市| 碌曲县| 大方县| 甘洛县| 融水| 吴川市| 册亨县| 乌拉特后旗| 永寿县| 凯里市| 淮安市| 龙南县| 武安市| 曲靖市| 商丘市| 彭山县| 西乌| 扎兰屯市| 淳化县| 乐昌市| 隆安县| 乳源| 成安县| 托里县| 青阳县| 慈溪市| 万山特区| 稷山县| 纳雍县| 图木舒克市| 东乡县| 新沂市| 邹平县|