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

詳解Vue2如何監(jiān)聽數(shù)組的變化

 更新時(shí)間:2024年03月20日 15:16:11   作者:接著奏樂接著舞。  
這篇文章主要來和大家詳細(xì)探討一下Vue2中是如何監(jiān)聽數(shù)組的變化的,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

前言

眾所周知,vue2的響應(yīng)式原理是 數(shù)據(jù)劫持結(jié)合發(fā)布訂閱模式.具體是通過Object.defineProperty()方法來劫持各個(gè)屬性的getter和setter,從而能夠監(jiān)聽到數(shù)據(jù)的變化。,但是Object.defineProperty不能監(jiān)聽數(shù)組的變化那么vue2是怎么實(shí)現(xiàn)數(shù)組響應(yīng)式的呢?而且在日常開發(fā)中,我們會(huì)發(fā)現(xiàn)不能直接修改數(shù)組的length長(zhǎng)度,也不能通過數(shù)組下標(biāo)的方式修改數(shù)據(jù),比如:arr[0]=123這種方式不能響應(yīng)式。

那么,vue2是如何實(shí)現(xiàn)的呢?

Vue2內(nèi)部通過重寫數(shù)組的原型方法來監(jiān)聽數(shù)組的變動(dòng)

具體來說,Vue2首先獲取到數(shù)組的原型,然后創(chuàng)建一個(gè)新的對(duì)象繼承自該原型,接著將這個(gè)新對(duì)象的原型上的七個(gè)能夠修改數(shù)組自身的方法(push、pop、shift、unshift、splice、sort、reverse)進(jìn)行重寫。這些方法在執(zhí)行時(shí),除了執(zhí)行其原有的邏輯之外,還會(huì)觸發(fā)視圖更新。

以下是一個(gè)簡(jiǎn)化的重寫示例:

// 獲取數(shù)組的原型
const arrayProto = Array.prototype;
// 創(chuàng)建一個(gè)新的對(duì)象,該對(duì)象的原型就是arrayProto
const arrayMethods = Object.create(arrayProto);

// 需要被改寫的方法
const methodsToPatch = [
  'push',
  'pop',
  'shift',
  'unshift',
  'splice',
  'sort',
  'reverse'
];

methodsToPatch.forEach(function(method) {
  // 緩存原始方法
  const original = arrayProto[method];
  // 定義新的方法
  Object.defineProperty(arrayMethods, method, {
    value: function mutator(...args) {
      // 先執(zhí)行原始方法
      const result = original.apply(this, args);
      // 獲取數(shù)組對(duì)象的__ob__屬性,__ob__是每個(gè)響應(yīng)式對(duì)象都有的一個(gè)屬性,指向該對(duì)象的Observer實(shí)例
      const ob = this.__ob__;
      // 如果方法是新增元素的操作,將新增的元素轉(zhuǎn)換為響應(yīng)式
      let inserted;
      switch (method) {
        case 'push':
        case 'unshift':
          inserted = args;
          break;
        case 'splice':
          inserted = args.slice(2);
          break;
      }
      if (inserted) ob.observeArray(inserted);
      // 通知變更
      ob.dep.notify();
      return result;
    },
    configurable: true,
    enumerable: false,
    writable: true
  });
});

如何使用

在初始化響應(yīng)式數(shù)據(jù)時(shí),Vue會(huì)判斷一個(gè)對(duì)象是否是數(shù)組。如果是數(shù)組,Vue則會(huì)將這個(gè)數(shù)組的原型指向上面提到的arrayMethods,從而使得這個(gè)數(shù)組調(diào)用7個(gè)修改自身的方法時(shí),能夠觸發(fā)視圖的更新。這一過程主要是在Observer類的實(shí)例化過程中完成的。

if (Array.isArray(value)) {
  if (hasProto) {
    protoAugment(value, arrayMethods);
  } else {
    copyAugment(value, arrayMethods, arrayKeys);
  }
  this.observeArray(value);
}

小結(jié)

通過這種方式,Vue 2可以監(jiān)測(cè)到數(shù)組的變化并作出響應(yīng)。這種方法雖然巧妙,但有其局限性,比如直接通過索引設(shè)置數(shù)組元素的值或修改數(shù)組長(zhǎng)度等操作,是無法被檢測(cè)到的。Vue 3中采用了Proxy代替了這種實(shí)現(xiàn)方式,能夠更好地解決這些問題。

解決方式

雖然Object.defineProperty本身無法攔截?cái)?shù)組索引的直接修改或數(shù)組長(zhǎng)度的變化,Vue 2提供了幾種方法來解決這個(gè)限制,確保開發(fā)者仍然可以以響應(yīng)式的方式更新數(shù)組:

使用Vue.set 或 vm.$set

為了解決直接通過索引修改數(shù)組元素的問題,Vue 2引入了Vue.set函數(shù)和vm.$set實(shí)例方法。這兩個(gè)方法允許開發(fā)者在指定索引處插入或替換數(shù)組元素,同時(shí)保證變化是響應(yīng)式的。

// 假設(shè)有一個(gè)Vue組件的data如下:
data() {
  return {
    fruits: ['apple', 'banana', 'cherry']
  };
},
methods: {
  updateFruit() {
    this.$set(this.fruits, 1, 'orange'); // 將索引1處的'banana'替換為'orange'
  }
}

使用數(shù)組的splice方法

另一個(gè)解決方案是使用數(shù)組的splice方法。splice不僅可以在數(shù)組中添加/刪除項(xiàng)目,而且由于Vue重寫了這個(gè)方法,使用它進(jìn)行的任何操作都會(huì)觸發(fā)視圖更新。

updateFruit() {
  this.fruits.splice(1, 1, 'orange'); // 同樣的效果,替換操作
}

響應(yīng)式系統(tǒng)的限制與規(guī)避策略

雖然Vue的響應(yīng)式系統(tǒng)提供了強(qiáng)大的數(shù)據(jù)綁定能力,但了解其內(nèi)部工作原理和限制對(duì)于開發(fā)高效、可維護(hù)的Vue應(yīng)用至關(guān)重要。通過正確地使用Vue提供的工具和方法(如Vue.set、vm.$set和splice),開發(fā)者可以確保即使是那些原生JavaScript限制下不可直接偵測(cè)的變化,也能被Vue的響應(yīng)式系統(tǒng)捕獲并正確地更新視圖。

面試題

Object.defineProperty如何監(jiān)聽數(shù)組?為什么無法獲取數(shù)組的變化?

Object.defineProperty 本身并不直接用于監(jiān)聽數(shù)組的變化,因?yàn)樗窃O(shè)計(jì)來劫持和監(jiān)聽對(duì)象屬性的讀取和寫入操作的。當(dāng)我們使用 Object.defineProperty 對(duì)對(duì)象的屬性進(jìn)行劫持時(shí),我們實(shí)際上是在設(shè)置屬性的 getter 和 setter,這樣每當(dāng)屬性被訪問或修改時(shí),我們就可以執(zhí)行自定義的邏輯,比如通知視圖進(jìn)行更新。然而,當(dāng)應(yīng)用到數(shù)組上時(shí),存在幾個(gè)核心限制使得 Object.defineProperty 無法有效地監(jiān)聽數(shù)組的變化:

1. 數(shù)組索引的修改

當(dāng)通過索引直接修改數(shù)組(如 arr[0] = 'new value')時(shí),這實(shí)際上是一個(gè)屬性賦值操作。雖然理論上可以對(duì)數(shù)組的每個(gè)索引使用 Object.defineProperty 來監(jiān)聽變化,但這在實(shí)踐中是不可行的,因?yàn)椋?/p>

性能問題:數(shù)組可能非常大,為每個(gè)索引設(shè)置 getter 和 setter 會(huì)極大地影響性能。

動(dòng)態(tài)性問題:數(shù)組長(zhǎng)度是動(dòng)態(tài)變化的,每次數(shù)組變化時(shí)都需要重新為新的索引設(shè)置劫持,這在技術(shù)上是復(fù)雜且低效的。

2. 修改數(shù)組長(zhǎng)度

直接修改數(shù)組的 length 屬性(例如,通過設(shè)置 arr.length = 0 來清空數(shù)組),這種操作同樣無法被 Object.defineProperty 直接偵測(cè)到。這是因?yàn)?length 屬性的變化不會(huì)觸發(fā)索引屬性的 setter。

3. 使用數(shù)組方法

數(shù)組的方法(如 push、pop、splice 等)可以修改數(shù)組的內(nèi)容或結(jié)構(gòu)。這些操作不僅改變數(shù)組元素,有時(shí)還會(huì)改變數(shù)組的長(zhǎng)度。Object.defineProperty 無法直接攔截這些方法調(diào)用,因?yàn)樗鼈兪菙?shù)組原型上的方法,而不是數(shù)組實(shí)例上的直接屬性。

Vue 2 如何實(shí)現(xiàn)數(shù)組的響應(yīng)式

正因?yàn)樯鲜鱿拗?,Vue 2 選擇了一種不同的方式來實(shí)現(xiàn)對(duì)數(shù)組的響應(yīng)式監(jiān)聽:

重寫數(shù)組方法:Vue 2 通過修改數(shù)組實(shí)例的原型,將數(shù)組的一些方法(如 push、pop 等)重寫為可以觸發(fā)視圖更新的版本。當(dāng)這些重寫的方法被調(diào)用時(shí),Vue 可以捕獲到數(shù)組的變動(dòng)并觸發(fā)相應(yīng)的更新。

總結(jié)來說,Object.defineProperty 由于其內(nèi)在的機(jī)制和限制,并不能直接用于有效監(jiān)聽數(shù)組的變化。Vue 2 通過一種巧妙的方式繞過了這些限制,能夠?qū)崿F(xiàn)對(duì)數(shù)組操作的響應(yīng)式更新。

到此這篇關(guān)于詳解Vue2如何監(jiān)聽數(shù)組的變化的文章就介紹到這了,更多相關(guān)Vue2監(jiān)聽數(shù)組變化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue 動(dòng)態(tài)生成拓?fù)鋱D的示例

    vue 動(dòng)態(tài)生成拓?fù)鋱D的示例

    這篇文章主要介紹了vue 動(dòng)態(tài)生成拓?fù)鋱D的示例,幫助大家更好的理解和使用vue框架,感興趣的朋友可以了解下
    2021-01-01
  • vue中的路由跳轉(zhuǎn)tabBar圖片和文字的高亮效果

    vue中的路由跳轉(zhuǎn)tabBar圖片和文字的高亮效果

    這篇文章主要介紹了vue中的路由跳轉(zhuǎn)tabBar圖片和文字的高亮效果,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • 詳解vuex中mutation/action的傳參方式

    詳解vuex中mutation/action的傳參方式

    這篇文章主要介紹了詳解vuex中mutation/action的傳參方式,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-08-08
  • Monaco-editor 的 JSON Schema 配置及使用介紹

    Monaco-editor 的 JSON Schema 配置及使用介紹

    這篇文章主要為大家介紹了Monaco-editor 的 JSON Schema 配置及使用介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • vue2.0基于vue-cli+element-ui制作樹形treeTable

    vue2.0基于vue-cli+element-ui制作樹形treeTable

    這篇文章主要介紹了vue2.0基于vue-cli+element-ui制作樹形treeTable,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Vite打包項(xiàng)目后圖片丟失的簡(jiǎn)單解決方法

    Vite打包項(xiàng)目后圖片丟失的簡(jiǎn)單解決方法

    vue項(xiàng)目完成打包上線的時(shí)候很多人都會(huì)碰到靜態(tài)資源找不到的情況,下面這篇文章主要給大家介紹了關(guān)于Vite打包項(xiàng)目后圖片丟失的簡(jiǎn)單解決方法,需要的朋友可以參考下
    2023-05-05
  • Vue父組件調(diào)用子組件事件方法

    Vue父組件調(diào)用子組件事件方法

    下面小編就為大家分享一篇Vue父組件調(diào)用子組件事件方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-02-02
  • vue3中使用editor.js的詳細(xì)步驟記錄

    vue3中使用editor.js的詳細(xì)步驟記錄

    富文本編輯器作為直接與用戶交互的內(nèi)容輸入生產(chǎn)工具,對(duì)大家的項(xiàng)目來說非常重要,下面這篇文章主要給大家介紹了關(guān)于vue3中使用editor.js的詳細(xì)步驟,需要的朋友可以參考下
    2024-01-01
  • vue3封裝京東商品詳情頁放大鏡效果組件

    vue3封裝京東商品詳情頁放大鏡效果組件

    這篇文章主要為大家詳細(xì)介紹了vue3封裝類似京東商品詳情頁放大鏡效果組件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • vue實(shí)現(xiàn)樹形菜單效果

    vue實(shí)現(xiàn)樹形菜單效果

    這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)樹形菜單效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03

最新評(píng)論