簡單介紹Vue之vue.$set()方法原始碼案例

大雄45發表於2021-12-09
導讀 這篇文章主要介紹了Vue之vue.$set()方法原始碼案例詳解,本篇文章透過簡要的案例,講解了該項技術的瞭解與使用,以下就是詳細內容,需要的朋友可以參考下

在使用vue開發專案的過程中,經常會遇到這樣的問題:當vue的data裡邊宣告或者已經賦值過的物件或者陣列(陣列裡邊的值是物件)時,向物件中新增新的屬性,如果更新此屬性的值,是不會更新檢視的。

這是因為新加入的屬性不是響應式的,因此不會觸發檢視的更新,通常使用靜態方法Vue.set()或者例項方法this.$set()解決 ,使用方式:

物件:this.$set(target,key, value)

陣列:this.$set(target,index, value)

但不管是靜態方法Vue.set()還是例項方法this.$set(),他們底層的實現邏輯是一樣的,實現邏輯如下:

/**
 * Set a property on an object. Adds the new property and
 * triggers change notification if the property doesn't
 * already exist.
 */
export function set (target: Array| Object, key: any, val: any): any {
  // 首先判斷如果傳入的目標物件是undefined, null, primitive(原始值),或丟擲警告
  if (process.env.NODE_ENV !== 'production' &&
    (isUndef(target) || isPrimitive(target))
  ) {
    warn(`Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}`)
  }
  // 判斷目標物件target是陣列,並且key是合法的索引
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    // 取目標陣列的length值和key中較大的值作為target的length屬性
    target.length = Math.max(target.length, key)
    // 透過splice對key位置的元素進行替換
    target.splice(key, 1, val)
    return val
  }
  // 如果key在目標物件中已經存在,則直接賦值
  if (key in target && !(key in Object.prototype)) {
    target[key] = val
    return val
  }
  // 獲取target中的observer物件
  const ob = (target: any).__ob__
  // 如果target是vue例項或者$data直接返回
  if (target._isVue || (ob && ob.vmCount)) {
    process.env.NODE_ENV !== 'production' && warn(
      'Avoid adding reactive properties to a Vue instance or its root $data ' +
      'at runtime - declare it upfront in the data option.'
    )
    return val
  }
  // 如果ob不存在,說明target不是響應式物件,直接賦值,不觸發檢視更新
  if (!ob) {
    target[key] = val
    return val
  }
  // 如果ob存在,把key設定為響應式屬性
  defineReactive(ob.value, key, val)
  // 傳送通知,觸發檢視更新
  ob.dep.notify()
  return val
}

以上是vue 中set方法的原始碼,在這裡需要特別注意的是,在對陣列進行處理時,所用的splice方法並不是陣列本身的方法,而是在vue中封裝的具有響應式的陣列方法。

到此這篇關於Vue之vue.$set()方法原始碼案例詳解的文章就介紹到這了,感謝大家的支援。

原文來自:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69955379/viewspace-2792157/,如需轉載,請註明出處,否則將追究法律責任。

相關文章