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

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

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

一,前言

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

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

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

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

3.observe 方法最終返回一個(gè) Observer 類

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

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

6.在 defineReactive 中,如果屬性值為對象類型就繼續(xù)調(diào)用 observe 對當(dāng)前的對象屬性進(jìn)行觀測(即遞歸步驟 3~5),這樣就實(shí)現(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: {} } } }
});

當(dāng) data 中的屬性為數(shù)組時(shí),Vue 是如何進(jìn)行處理的

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

1,當(dāng)前邏輯分析

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

核心目標(biāo)是要實(shí)現(xiàn)數(shù)組的響應(yīng)式:

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

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

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

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

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

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

// 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ù)組類型進(jìn)行單獨(dú)處理:重寫 7 個(gè)變異方法
    }else{
      this.walk(value);
    }
  }
}

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

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

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

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

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

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

添加 new Observer 時(shí),對數(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 個(gè)重寫方法
  • array.proto.proto:原始方法

6,數(shù)組方法攔截的實(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:會(huì)在數(shù)組自身找到重寫的push方法,不會(huì)繼續(xù)到鏈上查找,實(shí)現(xiàn)攔截
  • arrayMethods.pop:數(shù)組自身沒找到重寫方法,繼續(xù)到鏈上找到原生pop方法

四,結(jié)尾

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

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

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

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

相關(guān)文章

  • elementUI多選框反選的實(shí)現(xiàn)代碼

    elementUI多選框反選的實(shí)現(xiàn)代碼

    這篇文章主要介紹了elementUI多選框反選的實(shí)現(xiàn)代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • 在vue中使用vant TreeSelect分類選擇組件操作

    在vue中使用vant TreeSelect分類選擇組件操作

    這篇文章主要介紹了在vue中使用vant TreeSelect分類選擇組件操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • Vue自定義指令實(shí)現(xiàn)對數(shù)字進(jìn)行千分位分隔

    Vue自定義指令實(shí)現(xiàn)對數(shù)字進(jìn)行千分位分隔

    對數(shù)字進(jìn)行千分位分隔后展示應(yīng)該是大部分同學(xué)都做過的功能了吧,常規(guī)的做法通常是編寫一個(gè)工具函數(shù)來對數(shù)據(jù)進(jìn)行轉(zhuǎn)換,那么我們可不可以通過vue指令來實(shí)現(xiàn)這一功能呢,下面我們就來探索一下呢
    2024-02-02
  • vue中el-input綁定鍵盤按鍵(按鍵修飾符)

    vue中el-input綁定鍵盤按鍵(按鍵修飾符)

    這篇文章主要介紹了vue中el-input綁定鍵盤按鍵(按鍵修飾符),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • 解決在Vue中使用axios用form表單出現(xiàn)的問題

    解決在Vue中使用axios用form表單出現(xiàn)的問題

    今天小編就為大家分享一篇解決在Vue中使用axios用form表單出現(xiàn)的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-10-10
  • vuejs中使用mixin局部混入/全局混入的方法詳解

    vuejs中使用mixin局部混入/全局混入的方法詳解

    混入可以省很多代碼(高類聚低耦合),還方便維護(hù),下面這篇文章主要給大家介紹了關(guān)于vuejs中使用mixin局部混入/全局混入的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-05-05
  • 詳解Vue-基本標(biāo)簽和自定義控件

    詳解Vue-基本標(biāo)簽和自定義控件

    本篇文章主要介紹了Vue-基本標(biāo)簽和自定義控件,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-03-03
  • 解決vue動(dòng)態(tài)下拉菜單 有數(shù)據(jù)未反應(yīng)的問題

    解決vue動(dòng)態(tài)下拉菜單 有數(shù)據(jù)未反應(yīng)的問題

    這篇文章主要介紹了解決vue動(dòng)態(tài)下拉菜單 有數(shù)據(jù)未反應(yīng)的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • vue遍歷生成的輸入框 綁定及修改值示例

    vue遍歷生成的輸入框 綁定及修改值示例

    今天小編就為大家分享一篇vue遍歷生成的輸入框 綁定及修改值示例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-10-10
  • Vue 搭建Vuex環(huán)境詳解

    Vue 搭建Vuex環(huán)境詳解

    這篇文章主要為大家介紹了Vue搭建Vuex環(huán)境,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-11-11

最新評論

枣强县| 尼木县| 林口县| 彰化市| 思茅市| 霸州市| 东明县| 敦煌市| 上蔡县| 建德市| 新竹市| 白河县| 墨脱县| 康保县| 桦南县| 海伦市| 汝州市| 秀山| 红原县| 浦北县| 彭州市| 沙雅县| 通渭县| 二手房| 汉沽区| 徐州市| 卢氏县| 虎林市| 亚东县| 三穗县| 公安县| 安义县| 泽库县| 衡东县| 英吉沙县| 泰来县| 集安市| 烟台市| 平果县| 若尔盖县| 黄平县|