国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

根據(jù)調(diào)試工具看Vue源碼之computed(二)

U2FsdGVkX1x / 1703人閱讀

摘要:回顧上回提到,計(jì)算屬性的緩存與這個(gè)類的屬性有關(guān),那么這次我們接著來看下,屬性到底取決于什么情況來變化,從而對(duì)進(jìn)行緩存。

回顧
上回提到,computed————計(jì)算屬性的緩存與Watcher這個(gè)類的dirty屬性有關(guān),那么這次我們接著來看下,dirty屬性到底取決于什么情況來變化,從而對(duì)computed進(jìn)行緩存。
依賴收集

切入正題之前,我們先來看一個(gè)問題:如果一個(gè)computed的結(jié)果是受data屬性下的值影響的,那么如何去捕獲因某個(gè)值變化而引起的computed的變化?答案是:依賴收集

根據(jù)上面的斷點(diǎn),在update函數(shù)執(zhí)行之前,我們注意到,有個(gè)reactiveSetter函數(shù)在它之前。我們點(diǎn)擊右側(cè)調(diào)用棧中的reactiveSetter,此時(shí)有一個(gè)函數(shù)特別醒目:defineReactive$$1,經(jīng)過又一次的斷點(diǎn),我們發(fā)現(xiàn)它在幾處都有調(diào)用:

initRender函數(shù)中調(diào)用

walk函數(shù)中調(diào)用

在實(shí)際斷點(diǎn)調(diào)試的時(shí)候,我們很容易可以知道存在這樣的,同時(shí)也是與本文有關(guān)的調(diào)用順序(從下往上):

defineReactive$$1

walk

Observer

observe

initData

initState

...

Observer

根據(jù)上邊提供的調(diào)用順序,我們重點(diǎn)看一下幾個(gè)關(guān)鍵的函數(shù):

observe
/**
 * Attempt to create an observer instance for a value,
 * returns the new observer if successfully observed,
 * or the existing observer if the value already has one.
 */
function observe (value, asRootData) {
  if (!isObject(value) || value instanceof VNode) {
    return
  }
  var ob;
  if (hasOwn(value, "__ob__") && value.__ob__ instanceof Observer) {
    ob = value.__ob__;
  } else if (
    shouldObserve &&
    !isServerRendering() &&
    (Array.isArray(value) || isPlainObject(value)) &&
    Object.isExtensible(value) &&
    !value._isVue
  ) {
    ob = new Observer(value);
  }
  if (asRootData && ob) {
    ob.vmCount++;
  }
  return ob
}

光看注釋我們都能知道,observe函數(shù)的作用是:為某個(gè)值創(chuàng)建一個(gè)observer實(shí)例,隨后將這個(gè)observer實(shí)例返回,在這里起到一個(gè)對(duì)值進(jìn)行篩選的作用

Observer
/**
 * Observer class that is attached to each observed
 * object. Once attached, the observer converts the target
 * object"s property keys into getter/setters that
 * collect dependencies and dispatch updates.
 */
var Observer = function Observer (value) {
  this.value = value;
  this.dep = new Dep();
  this.vmCount = 0;
  def(value, "__ob__", this);
  if (Array.isArray(value)) {
    if (hasProto) {
      protoAugment(value, arrayMethods);
    } else {
      copyAugment(value, arrayMethods, arrayKeys);
    }
    this.observeArray(value);
  } else {
    this.walk(value);
  }
};

注釋大意:

每個(gè)被觀察的對(duì)象都附屬于Observer類。每次對(duì)對(duì)象的觀察都會(huì)將它的 gettersetter屬性覆蓋,用以收集依賴以及觸發(fā)更新
walk && defineReactive$$1
Observer.prototype.walk = function walk (obj) {
  var keys = Object.keys(obj);
  for (var i = 0; i < keys.length; i++) {
    defineReactive$$1(obj, keys[i]);
  }
};

/**
 * Define a reactive property on an Object.
 */
function defineReactive$$1 (
  obj,
  key,
  val,
  customSetter,
  shallow
) {
  var dep = new Dep();

  var property = Object.getOwnPropertyDescriptor(obj, key);
  if (property && property.configurable === false) {
    return
  }

  // cater for pre-defined getter/setters
  var getter = property && property.get;
  var setter = property && property.set;
  if ((!getter || setter) && arguments.length === 2) {
    val = obj[key];
  }

  var childOb = !shallow && observe(val);
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter () {
      var value = getter ? getter.call(obj) : val;
      if (Dep.target) {
        dep.depend();
        if (childOb) {
          childOb.dep.depend();
          if (Array.isArray(value)) {
            dependArray(value);
          }
        }
      }
      return value
    },
    set: function reactiveSetter (newVal) {
      var value = getter ? getter.call(obj) : val;
      /* eslint-disable no-self-compare */
      if (newVal === value || (newVal !== newVal && value !== value)) {
        return
      }
      /* eslint-enable no-self-compare */
      if (process.env.NODE_ENV !== "production" && customSetter) {
        customSetter();
      }
      // #7981: for accessor properties without setter
      if (getter && !setter) { return }
      if (setter) {
        setter.call(obj, newVal);
      } else {
        val = newVal;
      }
      childOb = !shallow && observe(newVal);
      dep.notify();
    }
  });
}

其中,這端代碼是關(guān)鍵:

get: function reactiveGetter () {
      var value = getter ? getter.call(obj) : val;
      if (Dep.target) {
        dep.depend();
        if (childOb) {
          childOb.dep.depend();
          if (Array.isArray(value)) {
            dependArray(value);
          }
        }
      }
      return value
    },

如果閱讀了整段defineReactive$$1函數(shù),那么很容易就發(fā)現(xiàn),dep不過是Depnew出來的實(shí)例,那么即使不看Dep.prototype.depend的實(shí)現(xiàn),你也知道dep.depend()其實(shí)也就是在收集依賴。
另外,這段代碼意味著單單在data屬性下聲明一個(gè)變量是不會(huì)進(jìn)行依賴收集的,需要變量在程序中被調(diào)用,那么才會(huì)被收集到依賴中(其實(shí)這也是一種優(yōu)化)

Dep類下的相關(guān)實(shí)現(xiàn)
/**
 * A dep is an observable that can have multiple
 * directives subscribing to it.
 */
var Dep = function Dep () {
  this.id = uid++;
  this.subs = [];
};

Dep.prototype.addSub = function addSub (sub) {
  this.subs.push(sub);
};

Dep.prototype.removeSub = function removeSub (sub) {
  remove(this.subs, sub);
};

Dep.prototype.depend = function depend () {
  if (Dep.target) {
    Dep.target.addDep(this);
  }
};

Dep.prototype.notify = function notify () {
  // stabilize the subscriber list first
  var subs = this.subs.slice();
  if (process.env.NODE_ENV !== "production" && !config.async) {
    // subs aren"t sorted in scheduler if not running async
    // we need to sort them now to make sure they fire in correct
    // order
    subs.sort(function (a, b) { return a.id - b.id; });
  }
  for (var i = 0, l = subs.length; i < l; i++) {
    subs[i].update();
  }
};
總結(jié)

上面說了這么多未免有點(diǎn)亂,最后重新梳理下computed實(shí)現(xiàn)緩存的思路:

Vue在初始化data屬性時(shí),會(huì)將data屬性下相關(guān)的變量進(jìn)行觀察observe),同時(shí)重新設(shè)置它的gettersetter屬性,以便在其被調(diào)用時(shí)收集到它的依賴。

初始化computed

調(diào)用computed時(shí)判斷this.dirty屬性,為true時(shí)調(diào)用evaluate重新計(jì)算它的值并將this.dirty置為false,將值存在this.value?上,再調(diào)用computed則直接返回this.value

當(dāng)computed中依賴的值發(fā)生變化時(shí)會(huì)自動(dòng)觸發(fā)該值的setter屬性,緊接著調(diào)用notify函數(shù),遍歷一個(gè)subs數(shù)組,觸發(fā)update函數(shù)將this.dirty重置為true

當(dāng)computed再次被調(diào)用時(shí),由于this.dirty已經(jīng)是true,則會(huì)重新計(jì)算

掃描下方的二維碼或搜索「tony老師的前端補(bǔ)習(xí)班」關(guān)注我的微信公眾號(hào),那么就可以第一時(shí)間收到我的最新文章。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/102605.html

相關(guān)文章

  • 根據(jù)調(diào)試工具Vue源碼computed(一)

    摘要:官方定義類型詳細(xì)計(jì)算屬性將被混入到實(shí)例中。所有和的上下文自動(dòng)地綁定為實(shí)例計(jì)算屬性的結(jié)果會(huì)被緩存,除非依賴的響應(yīng)式屬性變化才會(huì)重新計(jì)算。注意,如果某個(gè)依賴比如非響應(yīng)式屬性在該實(shí)例范疇之外,則計(jì)算屬性是不會(huì)被更新的。 官方定義 類型:{ [key: string]: Function | { get: Function, set: Function } } 詳細(xì):計(jì)算屬性將被混入到 V...

    aisuhua 評(píng)論0 收藏0
  • 根據(jù)調(diào)試工具Vue源碼虛擬dom(

    摘要:前言上回我們提到,在子組件存在的情況下,父組件在執(zhí)行完鉤子函數(shù)之后生成子組件的實(shí)例,子組件執(zhí)行鉤子函數(shù),同時(shí)也檢查是否也有子組件,有則重復(fù)父組件的步驟,否則子組件的元素渲染深入了解在上一篇文章中其實(shí)我們提到一個(gè)函數(shù) 前言 上回我們提到,在子組件存在的情況下,父組件在執(zhí)行完created鉤子函數(shù)之后生成子組件的實(shí)例,子組件執(zhí)行created鉤子函數(shù),同時(shí)也檢查是否也有子組件,有則重復(fù)父組...

    zzir 評(píng)論0 收藏0
  • 前方來報(bào),八月最新資訊--關(guān)于vue2&3的最佳文章推薦

    摘要:哪吒別人的看法都是狗屁,你是誰只有你自己說了才算,這是爹教我的道理。哪吒去他個(gè)鳥命我命由我,不由天是魔是仙,我自己決定哪吒白白搭上一條人命,你傻不傻敖丙不傻誰和你做朋友太乙真人人是否能夠改變命運(yùn),我不曉得。我只曉得,不認(rèn)命是哪吒的命。 showImg(https://segmentfault.com/img/bVbwiGL?w=900&h=378); 出處 查看github最新的Vue...

    izhuhaodev 評(píng)論0 收藏0
  • 根據(jù)調(diào)試工具Vue源碼生命周期(一)

    摘要:由于工作中經(jīng)常使用調(diào)試工具來定位問題,覺著這東西真的挺好用。突然有一天受到啟發(fā),想著我學(xué)習(xí)源碼是否也可以通過調(diào)試工具呢因此,誕生了這篇文章來記錄我的一些學(xué)習(xí)成果,后續(xù)應(yīng)該會(huì)寫成一個(gè)系列。 由于工作中經(jīng)常使用chrome調(diào)試工具來定位問題,覺著這東西真的挺好用。突然有一天受到啟發(fā),想著:我學(xué)習(xí)源碼是否也可以通過調(diào)試工具呢? 因此,誕生了這篇文章來記錄我的一些學(xué)習(xí)成果,后續(xù)應(yīng)該會(huì)寫成一個(gè)...

    My_Oh_My 評(píng)論0 收藏0
  • 根據(jù)調(diào)試工具Vue源碼組件通信(一)

    摘要:根據(jù)調(diào)試工具看源碼之組件通信一根據(jù)調(diào)試工具看源碼之組件通信一在平時(shí)的業(yè)務(wù)開發(fā)中,相信在座的各位沒少用過組件通信。看完本文可以幫助你了解組件的通信方式及原理,從而進(jìn)一步加深對(duì)的理解,遠(yuǎn)離工程師的行列。 根據(jù)調(diào)試工具看Vue源碼之組件通信(一)## 根據(jù)調(diào)試工具看Vue源碼之組件通信(一) 在平時(shí)的業(yè)務(wù)開發(fā)中,相信在座的各位沒少用過組件通信。然而,對(duì)于一些新手/業(yè)務(wù)熟手來說,不懂技術(shù)原理往...

    付倫 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<