中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

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

如何實現Vue Object的變化偵測

發布時間:2020-08-03 11:45:12 來源:億速云 閱讀:124 作者:小豬 欄目:web開發

這篇文章主要講解了如何實現Vue Object的變化偵測,內容清晰明了,對此有興趣的小伙伴可以學習一下,相信大家閱讀完之后會有幫助。

數據觀察

Vue 中的對象變化偵測是通過Object.definePorperty實現的,但是Object.definePorperty的方式有缺陷,比如不能直接代理整個對象,每次都要循環遍歷對象的所有屬性;尤大大說之后會使用 ES6 中的Proxy 重寫這個部分。這篇博客介紹的是 Object.definePorperty 實現的對象偵測。

我們來看下面這段代碼,定義一個 defineReactive 函數,使用 Object.definePorperty 遍歷對象對象屬性的時候,設置 get 和 set;當對象屬性被讀取的時候觸發 get,對象屬性被設置的時候觸發 set。這樣就完成了對 data 的數據劫持,因為 Vue 的思想是響應式的,我們還需要收集這些變化。

function defineReactive(data,key,val){
  Object.definePorperty(data,key,{
    enumerable: true,
    configurable: true,
    get:function(){
      return val;
    }
    set :function (newVal){
      if(val === newVal){return}
      val = newVal;
    }
  })
}

依賴 收集

創建一個 Dep 類,在 get 中收集依賴,在 set 中新增依賴

class Dep{
  constructor(){
    this.arr = []
  }
  addSub(sub){
    this.arr.push(sub)
  }
   removeSub(sub){
    remove(this.arr,sub)
  }
  depend(){
    if(window.target){
      this.addSub(window.target)
    }
  }
  notify(){
    const arrs = this.arr.slice();
    for(let i = 0; i< arrs.lenth ;i ++){
      arrs[i].update();
    }
  }

}

function defineReactive(data,key,val){

  let dep = new Dep()
  Object.definePorperty(data,key,{
    enumerable: true,
    configurable: true,
    get:function(){
      dep.depend(); // 收集依賴
      return val;
    }
    set :function (newVal){
      if(val === newVal){return}
      val = newVal;
      dep.notify(); // 新增依賴
    }
  })
}

Observer 和 Watcher

我們發現 defineReactive 函數只能將某一個屬性轉換為 get/set 的形式,所以我們需要一個觀察者 Observer 用來幫助遞歸的偵測所有的 key

class Observer{
  constructor(value){
    this.value = value
  }
  if(!Array.isArry(value)){
    this.walk(value)
  }
  walk(obj){
    const keys = Object.keys(obj)
    for(let i = 0; i < keys.length ;i++){
      defineReactive(data,keys[i],obj[keys[i])
    }
  }
}

當這些依賴收集完成之后,我們要通知誰呢?怎么樣能讓視圖知道有變化更新?我們需要實現一個訂閱者 Watcher,
每次觸發 get 的時候都將 dep 指向自己,這樣就可以收集到依賴;
每次 set 的時候都循環調用 Watcher 的 update 方法。

class Watcher{
  constructor(vm,exp,cb){
    this.vm = vm;
    this.cb = cb;
    this.exp = exp;
    this.value = this.get();
  }
  get(){
    Dep.target = this;  // 將當前訂閱者指向自己
    var value = this.vm[exp];  // 觸發getter,添加自己到屬性訂閱器中
    Dep.target = null;  // 添加完畢,重置
    return value;
  }
  update(){
    const oldVal = this.value;
    this.value = this.get();
    this.cb.call(this.vm,this.value,oldVal)
  }
}

當 Vue 實例掛載好之后,模板都會綁定一個 Watcher,誰的屬性發生變化了就會通知響應的 Watcher,Watcher 再去通知編譯器 Compile 進行視圖更新

偵測沒辦法監聽到對象上屬性的新增和刪除

Vue 通過Object.definePorperty將對象的 key 轉化為 getter setter 的形式來進行偵測,但是無法追蹤到屬性的新增和刪除,所以 Vue 中提供了 vm.get 來實現

看完上述內容,是不是對如何實現Vue Object的變化偵測有進一步的了解,如果還想學習更多內容,歡迎關注億速云行業資訊頻道。

向AI問一下細節

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

AI

桂阳县| 东城区| 安远县| 萍乡市| 新田县| 泗洪县| 永嘉县| 安新县| 桦甸市| 杭锦旗| 布拖县| 松滋市| 图们市| 瑞安市| 浦县| 宁都县| 荥经县| 高邮市| 高要市| 宁强县| 临海市| 肥西县| 益阳市| 疏勒县| 太仆寺旗| 横峰县| 中山市| 周至县| 潞西市| 九龙县| 长寿区| 治县。| 肇庆市| 辽源市| 斗六市| 客服| 华坪县| 邵东县| 缙云县| 天水市| 昌都县|