4. Vue的API-$set和$delete的原理

由於Vue2.6.*之前偵測數據變化都是經過Object.defineProperty實現,ES6以前都沒法提供元編程能力,因此沒法偵測對象的增長和刪除屬性,這個時候須要單獨對其進行處理。vue

set處理新增的屬性

set方法的做用是在object或者Array上設置一個屬性, 在Vue的原型上添加方法Vue.prototype.$set = set, set方法具體實現爲:react

function set (target, key, val) {
    if (isUndef(target) || isPrimitive(target)
    ) {
      warn(("Cannot set reactive property on undefined, null, or primitive value: " + ((target))));
    }
    // 對數組,直接添加, 觸發前面講到的splice攔截器
    if (Array.isArray(target) && isValidArrayIndex(key)) {
      target.length = Math.max(target.length, key);
      target.splice(key, 1, val);
      return val
    }
    //  key已經存在於target中,已經被偵測了變化,就能夠發送依賴通知
    if (key in target && !(key in Object.prototype)) {
      target[key] = val;
      return val
    }
    // 經過獲取ob來判斷target是不是響應式的
    var ob = (target).__ob__;
    // 經過_isVue的屬性來判斷target是不是vue的實例
    if (target._isVue || (ob && ob.vmCount)) {
      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__屬性就不作處理
    if (!ob) {
      target[key] = val;
      return val
    }
    //  轉化爲getter/setter形式,並向target的依賴通知變化
    defineReactive$$1(ob.value, key, val);
    ob.dep.notify();
    return val
  }
複製代碼

del方法原理

del方法能夠刪除Object或者Array的某個屬性,在Vue原型上掛載Vue.prototype.$delete = del;編程

/**
   * Delete a property and trigger change if necessary.
   */
  function del (target, key) {
    // 若是是數組,則直接刪除
    if (Array.isArray(target) && isValidArrayIndex(key)) {
      target.splice(key, 1);
      return
    }
    // 與set方法一致
    var ob = (target).__ob__;
    if (target._isVue || (ob && ob.vmCount)) {
      warn(
        'Avoid deleting properties on a Vue instance or its root $data ' +
        '- just set it to null.'
      );
      return
    }
    // 若是key不是target的屬性則直接返回
    if (!hasOwn(target, key)) {
      return
    }
    // 刪除屬性
    delete target[key];
    // 若是不是響應式數據,則返回
    if (!ob) {
      return
    }
    // 爲響應式數據的話,則通知依賴更新
    ob.dep.notify();
  }
複製代碼

這部分介紹了偵測數據的API,computed的實現原理在後面的初始化過程再介紹。數組

相關文章
相關標籤/搜索