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

深入詳解Vue3 ref底層實現(xiàn)原理

 更新時間:2023年04月25日 14:57:37   作者:矢心  
隨著現(xiàn)在vue3越來越普及,相應(yīng)的面試題也多了起來。說到vue3的面試題,有一個最經(jīng)典的就是對于實現(xiàn)ref和reactive這兩個方法的底層原理,本文就來和大家簡單講講吧

前言

隨著現(xiàn)在vue3越來越普及,相應(yīng)的面試題也多了起來

說到vue3的面試題,有一個最經(jīng)典的就是ref和reactive的區(qū)別,用法上的區(qū)別很明顯,大家都理解,對于實現(xiàn)這兩個方法的底層原理網(wǎng)上卻眾說紛壇,各有說法。

其中vue3的reactive的是用Proxy實現(xiàn)的這一點是明確的

這里講的就是這個ref,有說是使用Object.defineProperty實現(xiàn)的,有說是使用Proxy實現(xiàn)的,說法不一,到底哪些是正確的呢

下面說一下我自己的理解,如有誤請在評論區(qū)指出!謝謝

源碼解析

既然各方說法不一,那首先想到的就是直接去看vue3官方源碼不就好了,看別人不如自己實際動起來

通過node_modules依賴文件找到vue中實現(xiàn)ref的源碼

源碼如下:

為方便理解,把相關(guān)涉及到的源碼以及代碼含義加上注釋

function ref(value) { // ref方法
    return createRef(value, false);
}

function shallowRef(value) { // 淺層ref
    return createRef(value, true);
}

function createRef(rawValue, shallow) { // 創(chuàng)建ref
    if (isRef(rawValue)) { // 判斷是否為ref
        return rawValue;
    }
    return new RefImpl(rawValue, shallow); // 返回RefImpl實例對象
}

class RefImpl {
    constructor(value, __v_isShallow) { // 值,是否淺層ref
        this.__v_isShallow = __v_isShallow;
        this.dep = undefined;
        this.__v_isRef = true;
        this._rawValue = __v_isShallow ? value : toRaw(value);
        this._value = __v_isShallow ? value : toReactive(value);  // 判斷是否為淺層ref,否則調(diào)用toReactive,方法在下面
    }
    get value() { // getter方法 獲取value值
        trackRefValue(this);
        return this._value;
    }
    set value(newVal) { // setter方法 設(shè)置value值
        const useDirectValue = this.__v_isShallow || isShallow(newVal) || isReadonly(newVal);
        newVal = useDirectValue ? newVal : toRaw(newVal);
        if (hasChanged(newVal, this._rawValue)) {
            this._rawValue = newVal;
            this._value = useDirectValue ? newVal : toReactive(newVal); // 在value值更新時進行判斷是否為淺層ref,否則調(diào)用toReactive
            triggerRefValue(this, newVal);
        }
    }
}

const toReactive = (value) => isObject(value) ? reactive(value) : value; // 是否為對象,如果是則調(diào)用reactive

經(jīng)過一番閱讀理解,我們只需抓取關(guān)鍵信息即可

可以看到通過 ref(1) 的值在 RefImpl 類中為 _value ,然后使用class中的getset語法糖對該value值進行相應(yīng)的操作,獲取和賦值

再判斷為對象時才使用reactive()方法

實踐操作

從源碼上看,我們看到了,使用了class的get和set來對這個value值進行操作,那么我們自己動手實踐一下,看看怎么實現(xiàn)

這里把源碼的_value的口頭約定私有屬性形式改為es9新增加的#value形式

class RefImpl {
    #value = '' // #value 私有屬性

    constructor(value) {
        this.#value = value 
    }
    get value() {
        console.log('觸發(fā)獲取', this.#value)
        return this.#value
    }
    set value(newVal) {
        console.log('觸發(fā)更新', newVal)
        this.#value = newVal
    }
}

function ref(value) {
    return new RefImpl(value)
}

const test = ref('我是小濤測試')

setTimeout(() => {
  test.value = '我設(shè)置了值'
}, 2000)

可以看到,這個簡單的實例,也可以劫持數(shù)據(jù)的更新方便我們進行其他操作

class類的get和set是什么

到了這里,可以確定ref是使用class里的get/set進行數(shù)據(jù)劫持和更新的

而這個get/set實際是語法糖,本質(zhì)是js的特性,是劫持property(屬性)的一種方式

對象內(nèi)分為數(shù)據(jù)屬性訪問器屬性,訪問器屬性不包含數(shù)據(jù),是一對get和set方法

Getter 屬性訪問器(accessor)和 Setter 屬性修改器(mutator)

結(jié)論

綜上所述

所以一剛開始說的使用Object.defineProperty說法并不正確,因為Object.defineProperty()可以用來給修改對象屬性,然后使用到了getter/setter

Object.defineProperty()

所以使用了class的說法也并不正確,也是在對象內(nèi)使用訪問器屬性,使用到了getter/setter這兩個方法

Object.defineProperty() 方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現(xiàn)有屬性,并返回此對象。

Vue 將遍歷此對象所有的屬性,并使用Object.defineProperty把這些屬性全部轉(zhuǎn)為 getter/setter。

附上一張官方說法 官方鏈接

在對象內(nèi)也可以使用訪問器屬性

const test = {
  _value: '',
  get value() {
      console.log('觸發(fā)獲取', this._value)
      return this._value
  },
  set value(newVal) {
      console.log('觸發(fā)更新', newVal)
      this._value = newVal
  }
}

最后,其實簡化到最后發(fā)現(xiàn),都不會難以理解,所以保持探索態(tài)度,多看多學(xué),方是正途

到此這篇關(guān)于深入詳解Vue3 ref底層實現(xiàn)原理的文章就介紹到這了,更多相關(guān)Vue3 ref內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Vue中使用和移除總線Bus的注意事項詳解

    Vue中使用和移除總線Bus的注意事項詳解

    Vue中的總線Bus是一種通信機制,可用于組件間的數(shù)據(jù)傳遞和事件觸發(fā)。使用時需要注意Bus的命名和定義、監(jiān)聽和觸發(fā)事件的方法、移除和銷毀Bus的時機和方式等問題。合理使用總線Bus可以提高組件的復(fù)用性和可維護性,但過度依賴可能會導(dǎo)致代碼耦合和難以維護
    2023-04-04
  • Vue實現(xiàn) 點擊顯示再點擊隱藏效果(點擊頁面空白區(qū)域也隱藏效果)

    Vue實現(xiàn) 點擊顯示再點擊隱藏效果(點擊頁面空白區(qū)域也隱藏效果)

    這篇文章主要介紹了Vue實現(xiàn) 點擊顯示 再點擊隱藏 點擊頁面空白區(qū)域也隱藏效果,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-01-01
  • element-ui圖像組件、上傳組件以及分頁組件實現(xiàn)代碼

    element-ui圖像組件、上傳組件以及分頁組件實現(xiàn)代碼

    工作中碰到需要多圖上傳,在使用element-ui解決過程中碰到一些問題,在這里分享給大家,這篇文章主要給大家介紹了關(guān)于element-ui圖像組件、上傳組件以及分頁組件實現(xiàn)的相關(guān)資料,需要的朋友可以參考下
    2024-02-02
  • vue中tab選項卡的實現(xiàn)思路

    vue中tab選項卡的實現(xiàn)思路

    今天給大家分享vue中tab 選項卡的一些套路,非常不錯,具有一定的參考借鑒價值,需要的朋友參考下吧
    2018-11-11
  • Vue項目中設(shè)置背景圖片方法

    Vue項目中設(shè)置背景圖片方法

    下面小編就為大家分享一篇Vue項目中設(shè)置背景圖片方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-02-02
  • vue-cli3 項目優(yōu)化之通過 node 自動生成組件模板 generate View、Component

    vue-cli3 項目優(yōu)化之通過 node 自動生成組件模板 generate View、Component

    這篇文章主要介紹了vue-cli3 項目優(yōu)化之通過 node 自動生成組件模板 generate View、Component的相關(guān)知識,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-04-04
  • VueJs 將接口用webpack代理到本地的方法

    VueJs 將接口用webpack代理到本地的方法

    本篇文章主要介紹了VueJs 將接口用webpack代理到本地的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-11-11
  • 基于element-ui封裝表單金額輸入框的方法示例

    基于element-ui封裝表單金額輸入框的方法示例

    這篇文章主要介紹了基于element-ui封裝表單金額輸入框的方法示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • 對類Vue的MVVM前端庫的實現(xiàn)代碼

    對類Vue的MVVM前端庫的實現(xiàn)代碼

    這篇文章主要介紹了對類Vue的MVVM前端庫的實現(xiàn)代碼,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-09-09
  • vue 使用 sortable 實現(xiàn) el-table 拖拽排序功能

    vue 使用 sortable 實現(xiàn) el-table 拖拽排序功能

    這篇文章主要介紹了vue 使用 sortable 實現(xiàn) el-table 拖拽排序功能,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12

最新評論