成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

100行代碼帶你玩Vue響應(yīng)式

gclove / 1056人閱讀

摘要:響應(yīng)式原理看過官方文檔的同學(xué),對這張圖應(yīng)該已然相當(dāng)熟悉了。先擼為敬這里我們用不到行的代碼,實(shí)現(xiàn)了一個簡易的響應(yīng)式。當(dāng)然,這里如果不考慮期間的過程,我相信,行代碼之內(nèi)可以搞定。

Vue響應(yīng)式原理

看過vue官方文檔的同學(xué),對這張圖應(yīng)該已然相當(dāng)熟悉了。

vue的響應(yīng)式是如何實(shí)現(xiàn)的?

聽過太多回答,通過Object.defineProperty,可是再詳細(xì)的問時,對方渾然不知。

先擼為敬
const Observer = function(data) {
  for (let key in data) {
    defineReactive(data, key);
  }
}

const defineReactive = function(obj, key) {
  const dep = new Dep();
  let val = obj[key];
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get() {
      console.log("in get");
      dep.depend();
      return val;
    },
    set(newVal) {
      if (newVal === val) {
        return;
      }
      val = newVal;
      dep.notify();
    }
  });
}

const observe = function(data) {
  return new Observer(data);
}

const Vue = function(options) {
  const self = this;
  if (options && typeof options.data === "function") {
    this._data = options.data.apply(this);
  }

  this.mount = function() {
    new Watcher(self, self.render);
  }

  this.render = function() {
    with(self) {
      _data.text;
    }
  }

  observe(this._data);  
}

const Watcher = function(vm, fn) {
  const self = this;
  this.vm = vm;
  Dep.target = this;
  
  this.addDep = function(dep) {
    dep.addSub(self);
  }

  this.update = function() {
    console.log("in watcher update");
    fn();
  }

  this.value = fn();
  Dep.target = null;
}

const Dep = function() {
  const self = this;
  this.target = null;
  this.subs = [];
  this.depend = function() {
    if (Dep.target) {
      Dep.target.addDep(self);
    }
  }

  this.addSub = function(watcher) {
    self.subs.push(watcher);
  }

  this.notify = function() {
    for (let i = 0; i < self.subs.length; i += 1) {
      self.subs[i].update();
    }
  }
}

const vue = new Vue({
  data() {
    return {
      text: "hello world"
    };
  }
})

vue.mount(); // in get
vue._data.text = "123"; // in watcher update /n in get

這里我們用不到100行的代碼,實(shí)現(xiàn)了一個簡易的vue響應(yīng)式。當(dāng)然,這里如果不考慮期間的過程,我相信,40行代碼之內(nèi)可以搞定。但是我這里不想省略,為什么呢?我怕你把其中的過程自動忽略掉,怕別人問你相關(guān)東西的時候,明明自己看過了,卻被懟的啞口無言。總之,我是為了你好,多喝熱水。

Dep的作用是什么?
依賴收集器,這不是官方的名字蛤,我自己起的,為了好記。

用兩個例子來看看依賴收集器的作用吧。

例子1,毫無意義的渲染是不是沒必要?

const vm = new Vue({
    data() {
        return {
            text: "hello world",
            text2: "hey",
        }
    }
})

當(dāng)vm.text2的值發(fā)生變化時,會再次調(diào)用render,而template中卻沒有使用text2,所以這里處理render是不是毫無意義?

針對這個例子還記得我們上面模擬實(shí)現(xiàn)的沒,在Vuerender函數(shù)中,我們調(diào)用了本次渲染相關(guān)的值,所以,與渲染無關(guān)的值,并不會觸發(fā)get,也就不會在依賴收集器中添加到監(jiān)聽(addSub方法不會觸發(fā)),即使調(diào)用set賦值,notify中的subs也是空的。OK,繼續(xù)回歸demo,來一小波測試去印證下我說的吧。

const vue = new Vue({
  data() {
    return {
      text: "hello world",
      text2: "hey"
    };
  }
})

vue.mount(); // in get
vue._data.text = "456"; // nothing
vue._data.text2 = "123"; // in watcher update /n in get

例子2,多個Vue實(shí)例引用同一個data時,通知誰?是不是應(yīng)該倆都通知?

let commonData = {
  text: "hello world"
};

const vm1 = new Vue({
  data() {
    return commonData;
  }
})

const vm2 = new Vue({
  data() {
    return commonData;
  }
})

vm1.mount(); // in get
vm2.mount(); // in get
commonData.text = "hey" // 輸出了兩次 in watcher update /n in get

老規(guī)矩,自己代入進(jìn)去試試。

希望通過這兩個例子,你已經(jīng)大概清楚了Dep的作用,有沒有原來就那么回事的感覺?有就對了。總結(jié)一下吧(以下依賴收集器實(shí)為Dep):

vuedata初始化為一個Observer并對對象中的每個值,重寫了其中的get、set,data中的每個key,都有一個獨(dú)立的依賴收集器。

get中,向依賴收集器添加了監(jiān)聽

在mount時,實(shí)例了一個Wathcer,將收集器的目標(biāo)指向了當(dāng)前Watcher

data值發(fā)生變更時,觸發(fā)set,觸發(fā)了依賴收集器中的所有監(jiān)聽的更新,來觸發(fā)Watcher.update

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/94576.html

相關(guān)文章

  • 你玩轉(zhuǎn)prefetch, preload, dns-prefetch,defer和async

    摘要:緊接著發(fā)現(xiàn),于是又停了,瀏覽器下載并執(zhí)行完,繼續(xù)。,發(fā)現(xiàn),遂將中文字展示了出來。的執(zhí)行時間是在所有元素解析完成之后,事件觸發(fā)之前。的執(zhí)行時間是在當(dāng)前腳本下載完成后,所以多個是執(zhí)行順序是不固定的。至此,完美的結(jié)構(gòu)出爐了。 現(xiàn)代瀏覽器性能優(yōu)化-JS篇 眾所周知,JS的加載和執(zhí)行會阻塞瀏覽器渲染,所以目前業(yè)界普遍推薦把script放到之前,以解決js執(zhí)行時找不到dom等問題。但隨著現(xiàn)代瀏覽器...

    godiscoder 評論0 收藏0
  • 你玩轉(zhuǎn)prefetch, preload, dns-prefetch,defer和async

    摘要:緊接著發(fā)現(xiàn),于是又停了,瀏覽器下載并執(zhí)行完,繼續(xù)。,發(fā)現(xiàn),遂將中文字展示了出來。的執(zhí)行時間是在所有元素解析完成之后,事件觸發(fā)之前。的執(zhí)行時間是在當(dāng)前腳本下載完成后,所以多個是執(zhí)行順序是不固定的。至此,完美的結(jié)構(gòu)出爐了。 現(xiàn)代瀏覽器性能優(yōu)化-JS篇 眾所周知,JS的加載和執(zhí)行會阻塞瀏覽器渲染,所以目前業(yè)界普遍推薦把script放到之前,以解決js執(zhí)行時找不到dom等問題。但隨著現(xiàn)代瀏覽器...

    lewif 評論0 收藏0
  • 阿里小哥你玩轉(zhuǎn)JVM:揭秘try-catch-finally在JVM底層都干了些啥?

    摘要:當(dāng)觸發(fā)異常的字節(jié)碼的索引值在某個異常表?xiàng)l目的監(jiān)控范圍內(nèi),虛擬機(jī)會判斷所拋出的異常和該條目想要捕獲的異常是否匹配。 作者:李瑞杰目前就職于阿里巴巴,狂熱JVM愛好者讓我們準(zhǔn)備一個函數(shù):showImg(https://user-gold-cdn.xitu.io/2019/5/19/16acbce35adfefb7);然后,反編譯他的字節(jié)碼:showImg(https://user-gold-cd...

    番茄西紅柿 評論0 收藏0
  • 阿里小哥你玩轉(zhuǎn)JVM:揭秘try-catch-finally在JVM底層都干了些啥?

    摘要:當(dāng)觸發(fā)異常的字節(jié)碼的索引值在某個異常表?xiàng)l目的監(jiān)控范圍內(nèi),虛擬機(jī)會判斷所拋出的異常和該條目想要捕獲的異常是否匹配。 作者:李瑞杰目前就職于阿里巴巴,狂熱JVM愛好者讓我們準(zhǔn)備一個函數(shù):showImg(https://user-gold-cdn.xitu.io/2019/5/19/16acbce35adfefb7);然后,反編譯他的字節(jié)碼:showImg(https://user-gold-cd...

    番茄西紅柿 評論0 收藏0
  • 阿里小哥你玩轉(zhuǎn)JVM:揭秘try-catch-finally在JVM底層都干了些啥?

    摘要:當(dāng)觸發(fā)異常的字節(jié)碼的索引值在某個異常表?xiàng)l目的監(jiān)控范圍內(nèi),虛擬機(jī)會判斷所拋出的異常和該條目想要捕獲的異常是否匹配。 作者:李瑞杰目前就職于阿里巴巴,狂熱JVM愛好者讓我們準(zhǔn)備一個函數(shù):showImg(https://user-gold-cdn.xitu.io/2019/5/19/16acbce35adfefb7);然后,反編譯他的字節(jié)碼:showImg(https://user-gold-cd...

    lykops 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<