真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Proxy如何優(yōu)化vue的數(shù)據(jù)監(jiān)聽機(jī)制問題

這篇文章主要介紹Proxy如何優(yōu)化vue的數(shù)據(jù)監(jiān)聽機(jī)制問題,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

網(wǎng)站建設(shè)哪家好,找成都創(chuàng)新互聯(lián)!專注于網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、重慶小程序開發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了莘縣免費(fèi)建站歡迎大家使用!

vue2.x中的實(shí)現(xiàn)

其本質(zhì)是new Watcher(data, key, callback)的方式,而在調(diào)用之前是先將data中的所有屬性轉(zhuǎn)化成可監(jiān)聽的對(duì)象, 其主要就是利用Object.defineProperty,。

class Watcher{
  constructor(data, key, cb){
  }
}
//轉(zhuǎn)換成可監(jiān)聽對(duì)象
function observe(data){
  new Observer(data)
}
//修改數(shù)據(jù)的getter和setter
function defineReactive(obj, key){
  let value = obj[key];
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get(){
      return value;
    },
    set(newVal){
      value = newVal
    }
  })
}

Observer的實(shí)現(xiàn)很簡(jiǎn)單

class Observer {
  constructor(data){
    this.walk(data);
  }

  walk(data){
    for(var key in data) {
      // 這里不考慮嵌套的問題,否則的話需要遞歸調(diào)用walk
      defineReactive(data, key)
    }
  }
}

現(xiàn)在怎么將watcher和getter/setter聯(lián)系起來,vue的方法是添加一個(gè)依賴類:Dep

class Watcher{
  constructor(data, key, cb){
    this.cb = cb;
    Dep.target = this; //每次新建watcher的時(shí)候講給target賦值,對(duì)target的管理這里簡(jiǎn)化了vue的實(shí)現(xiàn)
    data[key];//調(diào)用getter,執(zhí)行addSub, 將target傳入對(duì)應(yīng)的dep; vue的實(shí)現(xiàn)本質(zhì)就是如此
  }
}
class Dep {
  constructor(){
    this.subs = [];
  }
  addSub(sub){
    this.subs.push(sub);
  }
  notify(){
    this.subs.forEach(sub => sub.cb())
  }
}
function defineReactive(obj, key){
  let value = obj[key];
  let dep = new Dep(); //每一個(gè)屬性都有一個(gè)對(duì)應(yīng)的dep,作為閉包保存
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get(){
      dep.addSub(Dep.target)
      Dep.target = null;
      return value;
    },
    set(newVal){
      value = newVal
      dep.notify();
    }
  })
}

以上就是vue的思路,vue3之所以要從新實(shí)現(xiàn),主要有這幾個(gè)原因:

  1. Object.defineProperty的性能開銷。

  2. defineReactive一開始就要對(duì)要監(jiān)聽的對(duì)象所有屬性都執(zhí)行一遍,因?yàn)閭鹘y(tǒng)方法要將一個(gè)對(duì)象轉(zhuǎn)換成可監(jiān)聽對(duì)象,只能如此。

  3. 添加刪除屬性的問題。

  4. 還有一點(diǎn)就是這個(gè)模塊被耦合到了vue里面,新版本可以單獨(dú)作為一個(gè)庫(kù)來使用。

然后我們來看看同樣的功能采用Proxy會(huì)怎樣實(shí)現(xiàn)。

Proxy的實(shí)現(xiàn)

將一個(gè)對(duì)象轉(zhuǎn)換成Proxy的方式很簡(jiǎn)單,只需要作為參數(shù)傳給proxy即可;

class Watcher {
  constructor(proxy, key, cb) {
    this.cb = cb;
    Dep.target = this;
    this.value = proxy[key];
  }
}
class Dep {
  constructor(){
    this.subs = []
  }
  addSub(sub){
    this.subs.push(sub);
  }
  notify(newVal){
    this.subs.forEach(sub => {
      sub.cb(newVal, sub.value);
      sub.value = newVal;
    })
  }
}
const observe = (obj) => {
  const deps = {};
  return new Proxy(obj, {
    get: function (target, key, receiver) {
      const dep = (deps[key] = deps[key] || new Dep);
      Dep.target && dep.addSub(Dep.target)
      Dep.target = null;
      return Reflect.get(target, key, receiver);
    },
    set: function (target, key, value, receiver) {
      const dep = (deps[key] = deps[key] || new Dep);
      Promise.resolve().then(() => {
        dep.notify(value);
      })
      return Reflect.set(target, key, value, receiver);
    }
  });
}
var state = observe({x:0})
new Watcher(state, 'x', function(n, o){
  console.log(n, o)
});
new Watcher(state, 'y', function(n, o){
  console.log(n, o)
});
state.x = 3;
state.y = 3;

也許一開始我們只關(guān)心x和y,那么就不會(huì)對(duì)其他的屬性做相應(yīng)的處理,除非添加watcher,其他時(shí)間target都是null

以上是“Proxy如何優(yōu)化vue的數(shù)據(jù)監(jiān)聽機(jī)制問題”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!


標(biāo)題名稱:Proxy如何優(yōu)化vue的數(shù)據(jù)監(jiān)聽機(jī)制問題
分享鏈接:http://weahome.cn/article/ieeojh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部