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

資訊專(zhuān)欄INFORMATION COLUMN

【前端進(jìn)階基礎(chǔ)】VUE響應(yīng)式數(shù)據(jù)原理 訂閱-發(fā)布模式解析

陳偉 / 1436人閱讀

摘要:其成員函數(shù)最主要的是和,前者用來(lái)設(shè)置某個(gè)的依賴(lài),后者則用來(lái)通知與這個(gè)依賴(lài)相關(guān)的來(lái)運(yùn)行其回調(diào)函數(shù)。也就是進(jìn)行數(shù)據(jù)更新操作。

vue框架的兩個(gè)抽象核心:虛擬DOM和相應(yīng)式數(shù)據(jù)原理

關(guān)于虛擬DOM的核心算法,我們上一章已經(jīng)基本解析過(guò)了,詳細(xì)的見(jiàn)
React && VUE Virtual Dom的Diff算法統(tǒng)一之路 snabbdom.js解讀

關(guān)于響應(yīng)式數(shù)據(jù)原理,我們先看張圖
你 ‘ (4).png

具體來(lái)講,要分以下幾步:

初始化實(shí)例對(duì)象時(shí)運(yùn)行initState, 建立好props, data 的鉤子以及其對(duì)象成員的Observer, 對(duì)于computed 屬性,則建立起所有對(duì)應(yīng)的 Watcher 并且通過(guò) Object.defineProperty 在vm對(duì)象上設(shè)置一個(gè)該屬性的 getter。同時(shí)還根據(jù)自定義的 watch 來(lái)建立相應(yīng)的 Watcher

執(zhí)行掛載操作,在掛載時(shí)建立一個(gè)直接對(duì)應(yīng)render(渲染)的 Watcher,并且編譯模板生成 render 函數(shù),執(zhí)行vm._update 來(lái)更新 DOM 。

此后每當(dāng)有數(shù)據(jù)改變,都將通知相應(yīng)的 Watcher 執(zhí)行回調(diào)函數(shù)。

Observer 劫持者
export class Observer {
  value: any;
  dep: Dep;
  vmCount: number; // number of vms that has this object as root $data

  constructor (value: any) {
    this.value = value
    this.dep = new Dep()
    this.vmCount = 0
    def(value, "__ob__", this)
    if (Array.isArray(value)) {
      const augment = hasProto
        ? protoAugment
        : copyAugment
      augment(value, arrayMethods, arrayKeys)
      this.observeArray(value)
    } else {
      this.walk(value)
    }
  }

  /**
   * Walk through each property and convert them into
   * getter/setters. This method should only be called when
   * value type is Object.
   */
  walk (obj: Object) {
    const keys = Object.keys(obj)
    for (let i = 0; i < keys.length; i++) {
      defineReactive(obj, keys[i], obj[keys[i]])
    }
  }

  /**
   * Observe a list of Array items.
   */
  observeArray (items: Array) {
    for (let i = 0, l = items.length; i < l; i++) {
      observe(items[i])
    }
  }
}

首先我們觀察到,new Observer()的時(shí)候,會(huì)進(jìn)行類(lèi)型的判斷

if (Array.isArray(value)) {
      const augment = hasProto
        ? protoAugment
        : copyAugment
      augment(value, arrayMethods, arrayKeys)
      this.observeArray(value)
    } else {
      this.walk(value)
    }

如果是數(shù)組類(lèi)型則會(huì)遞歸調(diào)用,建立依賴(lài)體系
否則則調(diào)用walk()函數(shù)去利用Object.defineProperty簡(jiǎn)歷依賴(lài)

那么defineReactive是如何實(shí)現(xiàn)的呢,如下

//省略了部分代碼
export function defineReactive (
 obj: Object,
 key: string,
 val: any,
 customSetter?: ?Function,
 shallow?: boolean
) {
  const dep = new Dep()
  ...
  Object.defineProperty(obj, key, {
      ...
      get: function reactiveGetter () {
        ...
        dep.depend()
        ...
        return value
      },
      set: function reactiveSetter (newVal) {
        ...
        dep.notify()
      }
    })
}

攔截器會(huì)分別在getter和setter上設(shè)置中間件去維護(hù)dep數(shù)組中的依賴(lài)關(guān)系

dep.depend()

dep.notify()

字面意思非常明顯,分別用于增加依賴(lài)和通知依賴(lài)變化關(guān)系

Dep (dependency // 依賴(lài))
class Dep {
  static target: ?Watcher;
  id: number;
  subs: Array;

  constructor () {
    this.id = uid++
    this.subs = []
  }

  addSub (sub: Watcher) {
    this.subs.push(sub)
  }

  removeSub (sub: Watcher) {
    remove(this.subs, sub)
  }

  depend () {
    if (Dep.target) {
      Dep.target.addDep(this)
    }
  }

  notify () {
    // stabilize the subscriber list first
    const subs = this.subs.slice()
    for (let i = 0, l = subs.length; i < l; i++) {
      subs[i].update()
    }
  }
}

Dep 就是一個(gè) Watcher 所對(duì)應(yīng)的數(shù)據(jù)依賴(lài),在這個(gè)對(duì)象中也存有一個(gè) subs 數(shù)組,用來(lái)保存和這個(gè)依賴(lài)有關(guān)的 Watcher。其成員函數(shù)最主要的是 depend 和 notify ,前者用來(lái)設(shè)置某個(gè) Watcher 的依賴(lài),后者則用來(lái)通知與這個(gè)依賴(lài)相關(guān)的 Watcher 來(lái)運(yùn)行其回調(diào)函數(shù)。

我們知道,Dom 上通過(guò)指令或者雙大括號(hào)綁定的數(shù)據(jù),會(huì)為數(shù)據(jù)進(jìn)行添加觀察者watcher,當(dāng)實(shí)例化Watcher的時(shí)候 會(huì)觸發(fā)屬性的getter方法,此時(shí)會(huì)調(diào)用dep.depend()。我們看一下depend方法:

depend () {
  if (Dep.target) {
    Dep.target.addDep(this)
  }
}

Dep.target 是什么東西呢?其實(shí)在進(jìn)行Watcher實(shí)例化的時(shí)候,會(huì)調(diào)用內(nèi)部的get函數(shù),開(kāi)始為他初始化

Watcher 觀察者

其中pushTarget 方法就是為Dep.target綁定此watcher實(shí)例,所以Dep.target.addDep(this)也就是執(zhí)行此實(shí)例中的addDep方法

addDep (dep: Dep) {
  ...
  dep.addSub(this)
}

這樣便為我們的dep實(shí)例添加了一個(gè)watcher實(shí)例。

接著當(dāng)我們更新data的時(shí)候,會(huì)觸發(fā)他的set方法,執(zhí)行dep.notify()函數(shù):

notify () {
  // stabilize the subscriber list first
  const subs = this.subs.slice()
  for (let i = 0, l = subs.length; i < l; i++) {
    subs[i].update()
  }
}

這里也就是遍歷dep中收集到的watcher實(shí)例,進(jìn)行update()。也就是進(jìn)行數(shù)據(jù)更新操作。這也就是簡(jiǎn)單的數(shù)據(jù)響應(yīng)式,其實(shí)還需要注意的是: 當(dāng)數(shù)據(jù)的getter觸發(fā)后,會(huì)收集依賴(lài),但也不是所有的觸發(fā)方式都會(huì)收集依賴(lài),只有通過(guò)watcher觸發(fā)的getter會(huì)收集依賴(lài):if (Dep.target) { dep.depend() },而所謂的被收集的依賴(lài)就是當(dāng)前watcher,DOM中的數(shù)據(jù)必須通過(guò)watcher來(lái)綁定,只通過(guò)watcher來(lái)讀取。

最后付一個(gè)函數(shù)timeline
的.png

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

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

相關(guān)文章

  • 源碼解析 —— Vue響應(yīng)數(shù)據(jù)

    摘要:下面我們會(huì)向大家解釋清楚為什么這個(gè)這么重要,以及它和的響應(yīng)式數(shù)據(jù)流有什么關(guān)系。源碼前面鋪墊這么多就是希望大家能理解接下來(lái)要講的響應(yīng)式數(shù)據(jù)流??偨Y(jié)講到這里大家應(yīng)該都能夠明白的響應(yīng)式數(shù)據(jù)流是如何實(shí)現(xiàn)的。 Vue、React介紹 目前前端社區(qū)比較推崇的框架有Vue 和 React,公司內(nèi)部許多端都自發(fā)的將原有的老技術(shù)方案(widget + jQuery)遷移到 Vue / React上了。我...

    LuDongWei 評(píng)論0 收藏0
  • vue.js響應(yīng)原理解析與實(shí)現(xiàn)

    摘要:今天,就我們就來(lái)一步步解析響應(yīng)式的原理,并且來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的。當(dāng)然,這個(gè)也只是一個(gè)簡(jiǎn)單的,來(lái)說(shuō)明響應(yīng)式的原理,真實(shí)的源碼會(huì)更加復(fù)雜,因?yàn)榧恿撕芏嗥渌壿?。接下?lái)我可能會(huì)將其與聯(lián)系起來(lái),實(shí)現(xiàn)和語(yǔ)法。 從很久之前就已經(jīng)接觸過(guò)了angularjs了,當(dāng)時(shí)就已經(jīng)了解到,angularjs是通過(guò)臟檢查來(lái)實(shí)現(xiàn)數(shù)據(jù)監(jiān)測(cè)以及頁(yè)面更新渲染。之后,再接觸了vue.js,當(dāng)時(shí)也一度很好奇vue.js是如何監(jiān)...

    Shihira 評(píng)論0 收藏0
  • 深入淺出Vue響應(yīng)原理

    摘要:總結(jié)最后我們依照下圖參考深入淺出,再來(lái)回顧下整個(gè)過(guò)程在后,會(huì)調(diào)用函數(shù)進(jìn)行初始化,也就是過(guò)程,在這個(gè)過(guò)程通過(guò)轉(zhuǎn)換成了的形式,來(lái)對(duì)數(shù)據(jù)追蹤變化,當(dāng)被設(shè)置的對(duì)象被讀取的時(shí)候會(huì)執(zhí)行函數(shù),而在當(dāng)被賦值的時(shí)候會(huì)執(zhí)行函數(shù)。 前言 Vue 最獨(dú)特的特性之一,是其非侵入性的響應(yīng)式系統(tǒng)。數(shù)據(jù)模型僅僅是普通的 JavaScript 對(duì)象。而當(dāng)你修改它們時(shí),視圖會(huì)進(jìn)行更新。這使得狀態(tài)管理非常簡(jiǎn)單直接,不過(guò)理解...

    yiliang 評(píng)論0 收藏0
  • Vue 進(jìn)階系列(一)之響應(yīng)原理及實(shí)現(xiàn)

    摘要:進(jìn)階系列一之響應(yīng)式原理及實(shí)現(xiàn)進(jìn)階系列二之插件原理及實(shí)現(xiàn)進(jìn)階系列三之函數(shù)原理及實(shí)現(xiàn)什么是響應(yīng)式表示一個(gè)狀態(tài)改變之后,如何動(dòng)態(tài)改變整個(gè)系統(tǒng),在實(shí)際項(xiàng)目應(yīng)用場(chǎng)景中即數(shù)據(jù)如何動(dòng)態(tài)改變。描述符必須是這兩種形式之一,但二者不能共存,不然會(huì)出現(xiàn)異常。 (關(guān)注福利,關(guān)注本公眾號(hào)回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實(shí)戰(zhàn)、面試指導(dǎo))showImg(https://githu...

    MonoLog 評(píng)論0 收藏0

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

0條評(píng)論

閱讀需要支付1元查看
<