溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Vue3?ref底層實現原理是什么

發(fā)布時間:2023-04-25 15:15:48 來源:億速云 閱讀:131 作者:iii 欄目:開發(fā)技術

這篇文章主要講解了“Vue3 ref底層實現原理是什么”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Vue3 ref底層實現原理是什么”吧!

源碼解析

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

通過node_modules依賴文件找到vue中實現ref的源碼

源碼如下:

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

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,否則調用toReactive,方法在下面
    }
    get value() { // getter方法 獲取value值
        trackRefValue(this);
        return this._value;
    }
    set value(newVal) { // setter方法 設置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,否則調用toReactive
            triggerRefValue(this, newVal);
        }
    }
}

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

經過一番閱讀理解,我們只需抓取關鍵信息即可

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

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

實踐操作

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

這里把源碼的_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 = '我設置了值'
}, 2000)

class類的get和set是什么

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

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

對象內分為數據屬性訪問器屬性,訪問器屬性不包含數據,是一對get和set方法

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

結論

綜上所述

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

Object.defineProperty()

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

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

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

在對象內也可以使用訪問器屬性

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

感謝各位的閱讀,以上就是“Vue3 ref底層實現原理是什么”的內容了,經過本文的學習后,相信大家對Vue3 ref底層實現原理是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI