Vue 怎么用 vm.$set() 解決對象新增屬性不能響應的問題 ?


受現代 JavaScript 的限制 ,Vue 無法檢測到對象屬性的添加或刪除。
由於 Vue 會在初始化實例時對屬性執行 getter/setter 轉化,所以屬性必須在 data 對象上存在才能讓 Vue 將它轉換為響應式的。

 

但是 Vue 提供了

 Vue.set (object, propertyName, value) / vm.$set (object, propertyName, value)

來實現為對象添加響應式屬性,那框架本身是如何實現的呢?

 

我們查看對應的 Vue 源碼:

vue/src/core/instance/index.js
export function set (target: Array<any> | Object, key: any, val: any): any {
  // target 為數組
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    // 修改數組的長度, 避免索引>數組長度導致splcie()執行有誤
    target.length = Math.max(target.length, key)
    // 利用數組的splice變異方法觸發響應式
    target.splice(key, 1, val)
    return val
  }
  // key 已經存在,直接修改屬性值
  if (key in target && !(key in Object.prototype)) {
    target[key] = val
    return val
  }
  const ob = (target: any).__ob__
  // target 本身就不是響應式數據, 直接賦值
  if (!ob) {
    target[key] = val
    return val
  }
  // 對屬性進行響應式處理
  defineReactive(ob.value, key, val)
  ob.dep.notify()
  return val
}

 

 

我們閱讀以上源碼可知,vm.$set 的實現原理是:

  • 如果目標是數組,直接使用數組的 splice 方法觸發相應式
  • 如果目標是對象,會先判讀屬性是否存在、對象是否是響應式,最終如果要對屬性進行響應式處理,則是通過調用 defineReactive 方法進行響應式處理( defineReactive 方法就是 Vue 在初始化對象時,給對象屬性采用 Object.defineProperty 動態添加 getter 和 setter 的功能所調用的方法)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM