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

Vue數(shù)組的劫持逐步分析講解

 更新時間:2023年01月06日 15:59:25   作者:BraveWangDev  
小編這次要給大家分享的是如何實現(xiàn)vue2.x數(shù)組劫持,文章內(nèi)容豐富,感興趣的小伙伴可以來了解一下,希望大家閱讀完這篇文章之后能夠有所收獲

一,前言

上篇,主要介紹了 Vue 數(shù)據(jù)初始化流程中,對象屬性的深層劫持是如何實現(xiàn)的

核心思路就是遞歸,主要流程如下;

1.通過 data = isFunction(data) ? data.call(vm) : data;處理后的 data 一定是對象類型

2.通過 data = observe(data)處理后的 data 就實現(xiàn)了數(shù)據(jù)的響應式(目前只有劫持)

3.observe 方法最終返回一個 Observer 類

4.Observer 類初始化時,通過 walk 遍歷屬性

5.對每一個屬性進行 defineReactive(Object.defineProperty)就實現(xiàn)對象屬性的單層數(shù)據(jù)劫持

6.在 defineReactive 中,如果屬性值為對象類型就繼續(xù)調(diào)用 observe 對當前的對象屬性進行觀測(即遞歸步驟 3~5),這樣就實現(xiàn)了對象屬性的深層數(shù)據(jù)劫持

本篇,繼續(xù)介紹 Vue 數(shù)據(jù)初始化流程中,對于數(shù)組類型的劫持

二,對象劫持回顧

1,Demo

data 數(shù)據(jù)中對象屬性的深層觀測,即對象屬性為對象(包含多層)的情況

let vm = new Vue({
  el: '#app',
  data() {
    return { message: 'Hello Vue', obj: { key: "val" }, a: { a: { a: {} } } }
});

當 data 中的屬性為數(shù)組時,Vue 是如何進行處理的

三,數(shù)組類型的處理

1,當前邏輯分析

按照當前版本的處理邏輯,所有對象類型會對被進行深層觀測,數(shù)組也不例外

let vm = new Vue({
  el: '#app',
  data() {
    return { message: 'Hello Vue', obj: { key: "val" }, arr:[1,2,3]}
  }
});

可以看到,數(shù)組中的每一項,都被添加了 get、set 方法,也就相當于實現(xiàn)了對數(shù)組的深層觀測

備注:Object.defineProperty支持數(shù)組數(shù)據(jù)類型的劫持

2,Vue 對性能的權(quán)衡

在 Vue2.x 中,不支持通過修改數(shù)組索引和長度的數(shù)據(jù)劫持;

那么,為什么原本可以實現(xiàn)對數(shù)組索引的觀測,Vue 卻選擇了不支持呢?

主要是考慮了性能問題,比如,數(shù)組中的數(shù)據(jù)量非常大時:

let vm = new Vue({
  el: '#app',
  data() {
    return { arr:new Array(9999) }
  }
});

這時,數(shù)組中 9999 條數(shù)據(jù),將全部被添加 get、set 方法

而這一套操作就比較費勁了:為了實現(xiàn)數(shù)組索引劫持,需要對數(shù)組中每一項進行處理

還有就是,雖然數(shù)組能夠通過 defineProperty 實現(xiàn)對索引更新劫持

但在實際開發(fā)場景真的需要嗎?似乎很少會使用 arr[888] = x 這種操作

所以,權(quán)衡性能和需求,Vue 源碼中沒有采用 defineProperty 對數(shù)組進行處理

當然,這也就導致了在 Vue 中無法通過直接修改索引、length 觸發(fā)視圖的更新

3,數(shù)組的劫持思路

核心目標是要實現(xiàn)數(shù)組的響應式:

Vue 認為這 7 個方法能夠改變原數(shù)組:push、pop、splice、shift、unshift、reverse、sort

所以,只要對這 7 個方法進行處理,就能劫持到數(shù)組的數(shù)據(jù)變化,實現(xiàn)數(shù)組數(shù)據(jù)的響應式

備注:這種實現(xiàn)思路,也直接導致了 vue2 修改數(shù)組的索引和長度不能觸發(fā)視圖更新

梳理對象屬性深層劫持的實現(xiàn):

  • 數(shù)據(jù)觀測入口:src/observe/index.js#observe方法
  • 如果數(shù)據(jù)為對象類型就 new Observer
  • Observer 初始化時,會遍歷對象屬性,逐一遞歸 Object.defineProperty

數(shù)組也是對象,所以,要把數(shù)組的處理邏輯單獨拆出來。即對 7 個變異方法進行重寫

// src/utils
/**
 * 判斷是否是數(shù)組
 * @param {*} val 
 * @returns 
 */
export function isArray(val) {
  return Array.isArray(val)
}
// src/observe/index.js
import { arrayMethods } from "./array";
class Observer {
  constructor(value) {
    if(isArray(value)){
      // 對數(shù)組類型進行單獨處理:重寫 7 個變異方法
    }else{
      this.walk(value);
    }
  }
}

4,數(shù)組方法的攔截思路

  • 重寫方法需要在原生方法基礎上,實現(xiàn)對數(shù)據(jù)變化的劫持操作
  • 僅對響應式數(shù)據(jù)中的數(shù)組進行方法重寫,不能影響非響應式數(shù)組

所以,對響應式數(shù)據(jù)中數(shù)組這 7 個方法進行攔截,即優(yōu)先使用重寫方法,其他方法還走原生邏輯

數(shù)組方法的查找,先查找自己身上的方法(即重寫方法),找不到再去鏈上查(原生方法)

5,數(shù)組方法重寫的實現(xiàn)

// src/Observer/array.js
// 拿到數(shù)組的原型方法
let oldArrayPrototype = Array.prototype;
// 原型繼承,將原型鏈向后移動 arrayMethods.__proto__ == oldArrayPrototype
export let arrayMethods = Object.create(oldArrayPrototype);
// 重寫能夠?qū)е略瓟?shù)組變化的七個方法
let methods = [
  'push',
  'pop',
  'shift',
  'unshift',
  'reverse',
  'sort',
  'splice'
]
// 在數(shù)組自身上進行方法重寫,對鏈上的同名方法進行攔截
methods.forEach(method => {
  arrayMethods[method] = function () {
    console.log('數(shù)組的方法進行重寫操作 method = ' + method)
  }
});

添加 new Observer 時,對數(shù)組方法重寫的邏輯:

// src/observe/index.js
import { arrayMethods } from "./array";
class Observer {
  constructor(value) {
    // 分別處理 value 為數(shù)組和對象兩種情況
    if(isArray(value)){
      value.__proto__ = arrayMethods; // 更改數(shù)組的原型方法
    }else{
      this.walk(value);
    }
  }
}

測試數(shù)組方法的重寫:

數(shù)組的鏈:

  • array.proto:包含 7 個重寫方法
  • array.proto.proto:原始方法

6,數(shù)組方法攔截的實現(xiàn)

// src/state.js#initData
function initData(vm) {
    let data = vm.$options.data;
    data = isFunction(data) ? data.call(vm) : data;
    observe(data);	// 在observe方法中new Observer執(zhí)行后,數(shù)組的原型方法已完成重寫
    // 測試數(shù)組方法的攔截效果
    data.arr.push(666); 
    data.arr.pop()
}

  • arrayMethods.push:會在數(shù)組自身找到重寫的push方法,不會繼續(xù)到鏈上查找,實現(xiàn)攔截
  • arrayMethods.pop:數(shù)組自身沒找到重寫方法,繼續(xù)到鏈上找到原生pop方法

四,結(jié)尾

本篇主要介紹了 Vue 數(shù)據(jù)初始化流程中,數(shù)組類型的數(shù)據(jù)劫持,核心有以下幾點:

出于對性能的考慮,Vue 沒有對數(shù)組類型的數(shù)據(jù)使用 Object.defineProperty 進行遞歸劫持,而是通過對能夠?qū)е略瓟?shù)組變化的 7 個方法進行攔截和重寫實現(xiàn)了數(shù)據(jù)劫持

下一篇,數(shù)據(jù)代理的實現(xiàn)

到此這篇關(guān)于Vue數(shù)組的劫持逐步分析講解的文章就介紹到這了,更多相關(guān)Vue數(shù)組劫持內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue中簡單彈框dialog的實現(xiàn)方法

    vue中簡單彈框dialog的實現(xiàn)方法

    下面小編就為大家分享一篇vue中簡單彈框dialog的實現(xiàn)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-02-02
  • Vue2實現(xiàn)自適應屏幕大小的兩種方法詳解

    Vue2實現(xiàn)自適應屏幕大小的兩種方法詳解

    這篇文章主要為大家詳細介紹了Vue2實現(xiàn)自適應屏幕大小的兩種方法,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2024-03-03
  • Vue中使用highlight.js實現(xiàn)代碼高亮顯示以及點擊復制

    Vue中使用highlight.js實現(xiàn)代碼高亮顯示以及點擊復制

    本文主要介紹了Vue中使用highlight.js實現(xiàn)代碼高亮顯示以及點擊復制,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Vue虛擬DOM詳細介紹

    Vue虛擬DOM詳細介紹

    虛擬DOM的概念是通過狀態(tài)生成一個虛擬節(jié)點樹,然后使用虛擬節(jié)點樹進行渲染。在渲染之前,會使用新生成的虛擬節(jié)點和上一次生成的虛擬節(jié)點進行對比,只渲染不同的部分
    2022-08-08
  • vue.js動畫中的js鉤子函數(shù)的實現(xiàn)

    vue.js動畫中的js鉤子函數(shù)的實現(xiàn)

    這篇文章主要介紹了vue.js動畫中的js鉤子函數(shù)的實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • VUE組件中的 Drawer 抽屜實現(xiàn)代碼

    VUE組件中的 Drawer 抽屜實現(xiàn)代碼

    這篇文章主要介紹了VUE組件 之 Drawer 抽屜 ,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-08-08
  • Vue 基礎語法之計算屬性(computed)、偵聽器(watch)、過濾器(filters)詳解

    Vue 基礎語法之計算屬性(computed)、偵聽器(watch)、過濾器(filters)詳解

    計算屬性就是 Vue 實例選項中的 computed,computed 的值是一個對象類型,對象中的屬性值為函數(shù),而且這個函數(shù)沒辦法接收參數(shù),這篇文章主要介紹了Vue 基礎語法之計算屬性(computed)、偵聽器(watch)、過濾器(filters)詳解,需要的朋友可以參考下
    2022-11-11
  • vue路由跳轉(zhuǎn)打開新窗口(window.open())和關(guān)閉窗口(window.close())

    vue路由跳轉(zhuǎn)打開新窗口(window.open())和關(guān)閉窗口(window.close())

    這篇文章主要介紹了vue路由跳轉(zhuǎn)打開新窗口(window.open())和關(guān)閉窗口(window.close())問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • vue?v-if未生效問題及解決

    vue?v-if未生效問題及解決

    這篇文章主要介紹了vue?v-if未生效問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • vue element-ui表格自定義動態(tài)列具體實現(xiàn)

    vue element-ui表格自定義動態(tài)列具體實現(xiàn)

    這周工作中遇見了一個表格動態(tài)列的需求,下面這篇文章主要給大家介紹了關(guān)于vue element-ui表格自定義動態(tài)列具體實現(xiàn)的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-06-06

最新評論