最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺析Proxy可以優(yōu)化vue的數(shù)據(jù)監(jiān)聽機(jī)制問題及實(shí)現(xiàn)思路

 更新時(shí)間:2018年11月29日 08:14:02   作者:南柯一夢(mèng)同志  
這篇文章主要介紹了淺析Proxy可以優(yōu)化vue的數(shù)據(jù)監(jiān)聽機(jī)制問題及實(shí)現(xiàn)思路,需要的朋友可以參考下

我們首先來(lái)看vue2.x中的實(shí)現(xiàn),為簡(jiǎn)單起見,我們這里不考慮多級(jí)嵌套,也不考慮數(shù)組

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)系起來(lái),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ù)來(lái)使用。

然后我們來(lái)看看同樣的功能采用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

總結(jié)

以上所述是小編給大家介紹的Proxy可以優(yōu)化vue的數(shù)據(jù)監(jiān)聽機(jī)制問題,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

最新評(píng)論

牙克石市| 尤溪县| 平原县| 长阳| 庆元县| 通河县| 大连市| 罗源县| 正定县| 时尚| 儋州市| 石楼县| 沙洋县| 开远市| 玉山县| 大竹县| 和平区| 运城市| 新竹县| 灯塔市| 西贡区| 寿阳县| 新巴尔虎右旗| 三江| 隆尧县| 巫溪县| 乐亭县| 遂宁市| 钦州市| 临邑县| 通辽市| 柯坪县| 绍兴市| 定安县| 通州区| 长岛县| 台南县| 海口市| 元朗区| 澄迈县| 合阳县|