欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解實現(xiàn)vue的數(shù)據(jù)響應式原理

 更新時間:2021年01月20日 14:09:49   作者:著實有點菜  
這篇文章主要介紹了詳解實現(xiàn)vue的數(shù)據(jù)響應式原理,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

這篇文章主要是給不了解或者沒接觸過 vue 響應式源碼的小伙伴們看的,其主要目的在于能對 vue 的響應式原理有個基本的認識和了解,如果在面試中被問到此類問題,能夠知道面試官想讓你回答的是什么?「PS:文中如有不對的地方,歡迎小伙伴們指正」

響應式的理解

響應式顧名思義就是數(shù)據(jù)變化,會引起視圖的更新。這篇文章主要分析 vue2.0 中對象和數(shù)組響應式原理的實現(xiàn),依賴收集和視圖更新我們留在下一篇文章分析。

在 vue 中,我們所說的響應式數(shù)據(jù),一般指的是數(shù)組類型和對象類型的數(shù)據(jù)。vue 內(nèi)部通過 Object.defineProperty 方法對對象的屬性進行劫持,數(shù)組則是通過重寫數(shù)組的方法實現(xiàn)的。下面我們就簡單實現(xiàn)一下。

首先我們定義一個需要被攔截的數(shù)據(jù)

const vm = new Vue({
 data () {
  return {
   count: 0,
   person: { name: 'xxx' },
   arr: [1, 2, 3]
  }
 }
})
let arrayMethods
function Vue (options) { // 這里只考慮對 data 數(shù)據(jù)的操作
 let data = options.data
 if (data) {
  data = this._data = typeof data === 'function' ? data.call(this) : data
 }
 observer (data)
}
function observer(data) { 
 if (typeof data !== 'object' || data === null) {
  return data
 }
 if (data.__ob__) { // 存在 __ob__ 屬性,說明已經(jīng)被攔截過了
  return data
 }
 new Observer(data)
}

這里的 arrayMethods、Observer 、 __ob__的實現(xiàn)和作用請繼續(xù)往下看

實現(xiàn) Observer 類

class Observer {
 constructor (data) {
  Object.defineProperty(data, '__ob__', { // 在 data 上定義 __ob__ 屬性,在數(shù)組劫持里需要用到
   enumerable: false, // 不可枚舉
   configurable: false, // 不可配置
   value: this // 值是 Observer 實例
  })
  if (Array.isArray(data)) { // 對數(shù)組進行攔截
   data.__proto__ = arrayMethods // 原型繼承
   this.observerArray(data)
  } else { // 對象進行攔截
   this.walk(data)
  }
 }
 walk (data) {
  const keys = Object.keys(data)
  for(let i = 0; i < keys.length; i++) {
   const key = keys[i]
   defineReactive(data, key, data[key])
  }
 }
 observerArray (data) { // 攔截數(shù)組中的每一項
  data.forEach(value => observer(value))
 }
}

對象的攔截

對象的劫持需要注意的幾點:

  • 遍歷對象,如果值還是對象類型,需要重新調(diào)用 observer 觀測方法
  • 如果設置的新值是對象類型,也需要被攔截
// 處理對象的攔截
function defineReactive(data, key, value) {
 observer(value) // 如果 value 值仍是對象類型,需要遞歸劫持
 Object.defineProperty(data, key, {
  get() {
   return value
  },
  set(newValue){
   if (newValue === value) return
   value = newValue
   observer(newValue) // 如果設置 newValue 值也是對象類型,需要被劫持
  }
 })
}

數(shù)組的劫持

數(shù)組的劫持需要注意的幾點:

  • 數(shù)組是使用函數(shù)劫持(切片編程)的思想,對數(shù)據(jù)進行攔截的
  • 數(shù)組里新增加的值,如果是對象類型,也需要被重新攔截
const oldArrayPrototype = Array.prototype
arrayMethods = Object.create(oldArrayPrototype)
const methods = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'] // 能夠改變原數(shù)組的方法
methods.forEach(method => {
 arrayMethods[methods] = function (...args) {
  const result = oldArrayPrototype[methods].call(this, ...args)
  const ob = this.__ob__ // this 就是調(diào)用改方法的數(shù)組
  let inserted; // 數(shù)組新增的項的集合,需要再對其進行攔截
  switch(methods) {
   case 'push': 
   case 'unshift':
    inserted = args
   case 'splice':
    inserted = args.slice(2) // 因為 splice 第二個參數(shù)后面的才是新增的
  }
  if (inserted) {
   ob.observerArray(inserted)
  }
  return result
 }
})

原理總結(jié)

在面試中,如果我們需要手寫 vue 的響應式原理,上面的代碼足矣。但是我們通過學習 vue 的源碼,如果在面試中能夠給出以下加以總結(jié)性的回答更能得到面試官的青睞。

vue 2.0 源碼的響應式原理:

  • 因為使用了遞歸的方式對對象進行攔截,所以數(shù)據(jù)層級越深,性能越差
  • 數(shù)組不使用 Object.defineProperty 的方式進行攔截,是因為如果數(shù)組項太多,性能會很差
  • 只有定義在 data 里的數(shù)據(jù)才會被攔截,后期我們通過 vm.newObj = 'xxx' 這種在實例上新增的方式新增的屬性是不會被攔截的
  • 改變數(shù)組的索引和長度,不會被攔截,因此不會引起視圖的更新
  • 如果在 data 上新增的屬性和更改數(shù)組的索引、長度,需要被攔截到,可以使用 $set 方法
  • 可以使用 Object.freeze 方法來優(yōu)化數(shù)據(jù),提高性能,使用了此方法的數(shù)據(jù)不會被重寫 set 和 get 方法

vue 3.0 源碼響應式原理:

  • 3.0 版本中使用了 proxy 代替了 Object.defineProperty ,其有13中攔截方式,不需要對對象和數(shù)組分別進行處理,也無需遞歸進行攔截,這也是其提升性能最大的地方
  • vue 3.0 版本響應式原理的簡單實現(xiàn)
const handler = {
 get (target, key) {
  if (typeof target[key] === 'object' && target[key] !== null) {
   return new Proxy(target[key], handler)
  }
  return Reflect.get(target, key)
 },
 set (target, key, value) {
  if(key === 'length') return true
  console.log('update')
  return Reflect.set(target, key, value)
 }
}
const obj = {
 arr: [1, 2, 3],
 count: { num: 1 }
}
// obj 是代理的目標對象, handler 是配置對象
const proxy = new Proxy(obj, handler)

到此這篇關于詳解實現(xiàn)vue的數(shù)據(jù)響應式原理的文章就介紹到這了,更多相關vue 數(shù)據(jù)響應式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家! 

相關文章

  • vue基于element-china-area-data插件實現(xiàn)省市區(qū)聯(lián)動

    vue基于element-china-area-data插件實現(xiàn)省市區(qū)聯(lián)動

    省市區(qū)聯(lián)動在日常開發(fā)中用的非常多,本文就介紹一下vue基于element-china-area-data插件實現(xiàn)省市區(qū)聯(lián)動,具有一定的參考價值,感興趣的可以了解一下
    2022-04-04
  • 關于vue3?解決getCurrentInstance?打包后線上環(huán)境報錯問題

    關于vue3?解決getCurrentInstance?打包后線上環(huán)境報錯問題

    這篇文章主要介紹了vue3?解決getCurrentInstance?打包后線上環(huán)境報錯問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-05-05
  • vue子組件封裝彈框只能執(zhí)行一次的mounted問題及解決

    vue子組件封裝彈框只能執(zhí)行一次的mounted問題及解決

    這篇文章主要介紹了vue子組件封裝彈框只能執(zhí)行一次的mounted問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Vue.js中的下載和調(diào)用方式

    Vue.js中的下載和調(diào)用方式

    這篇文章主要介紹了Vue.js中的下載和調(diào)用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • vue獲取后臺json字符串方式

    vue獲取后臺json字符串方式

    這篇文章主要介紹了vue獲取后臺json字符串方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • vue3下eslint配置方式

    vue3下eslint配置方式

    這篇文章主要介紹了vue3下eslint配置方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Vue分頁組件實現(xiàn)過程詳解

    Vue分頁組件實現(xiàn)過程詳解

    Web應用程序中資源分頁不僅對性能很有幫助,而且從用戶體驗的角度來說也是非常有用的。在這篇文章中,將了解如何使用Vue創(chuàng)建動態(tài)和可用的分頁組件
    2022-12-12
  • 詳解Vue如何進行分布式事務管理以及解決方案

    詳解Vue如何進行分布式事務管理以及解決方案

    在分布式系統(tǒng)中,事務管理是一個非常重要的問題,所以本文將介紹一下Vue中如何進行分布式事務管理以及分布式事務解決方案,希望對大家有所幫助
    2023-06-06
  • useEffect理解React、Vue設計理念的不同

    useEffect理解React、Vue設計理念的不同

    這篇文章主要為大家介紹了useEffect理解React、Vue設計理念的不同詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • 如何基于vue-cli3.0構(gòu)建功能完善的移動端架子

    如何基于vue-cli3.0構(gòu)建功能完善的移動端架子

    這篇文章主要介紹了基于vue-cli3.0構(gòu)建功能完善的移動端架子,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-04-04

最新評論