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

資訊專欄INFORMATION COLUMN

VueJS源碼學(xué)習(xí)——訂閱觀察者類

Godtoy / 3441人閱讀

摘要:實現(xiàn)了一個簡單的訂閱觀察者類,這個類被用于在數(shù)據(jù)修改時通知各個以觸發(fā)對應(yīng)的更新,從而實現(xiàn)數(shù)據(jù)的響應(yīng),這個會在后續(xù)的數(shù)據(jù)響應(yīng)化里提到。

observer 實現(xiàn)了一個簡單的訂閱觀察者類,這個類被用于在數(shù)據(jù)修改時通知各個 watcher 以觸發(fā)對應(yīng)的更新,從而實現(xiàn)數(shù)據(jù)的響應(yīng),這個會在后續(xù)的數(shù)據(jù)響應(yīng)化里提到。

原文地址
項目地址

src/observer src/observer/dep.js

depwatcher 引用

A dep is an observable that can have multiple

directives subscribing to it.
(dep 是一個可以被多個指令訂閱的觀察者)

// src/observer/dep.js

import { toArray } from "../util/index"

let uid = 0

export default function Dep () {
  this.id = uid++
  this.subs = []
}

Dep.target = null

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

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

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

Dep.prototype.notify = function () {
  var subs = toArray(this.subs)
  for (var i = 0, l = subs.length; i < l; i++) {
    subs[i].update()
  }
}

代碼量很少,但是幾個點暫時不明,一個是 this.subs.$remove(sub), 貌似是給數(shù)組添加了一個 remove 方法, target 擁有 addDep 方法, subs的 item 擁有 update 方法

更正,dep 類用來做依賴采集,是一個簡單的訂閱-觀察者模式,而 target 和 subs 用于存放 watcher,dep 類用于數(shù)據(jù)響應(yīng)化的實現(xiàn),在后續(xù)會講到這個

src/observer/array.js

實現(xiàn)了 arrayMethods 類,該類繼承了 array 對象:

...
const arrayProto = Array.prototype
export const arrayMethods = Object.create(arrayProto)
...

同時還對 array 拓展了 $set $remove 方法, 這就是在 dep.js 里使用到的 $remove 方法

def(
  arrayProto,
  "$set",
  function $set (index, val) {
    if (index >= this.length) {
      this.length = index + 1
    }
    return this.splice(index, 1, val)[0]
  }
)
def(
  arrayProto,
  "$remove",
  function $remove (item) {
    /* istanbul ignore if */
    if (!this.length) return
    var index = indexOf(this, item)
    if (index > -1) {
      return this.splice(index, 1)
    }
  }
)

def 方法的實現(xiàn):

export function def (obj, key, val, enumerable) {
  Object.defineProperty(obj, key, {
    value: val,
    enumerable: !!enumerable,
    writable: true,
    configurable: true
  })
}

除此之外, arrayMethods 重寫了

"push",
"pop",
"shift",
"unshift",
"splice",
"sort",
"reverse"

這些原型方法:

;[
  "push",
  "pop",
  "shift",
  "unshift",
  "splice",
  "sort",
  "reverse"
]
.forEach(function (method) {
  // cache original method
  var original = arrayProto[method]
  def(arrayMethods, method, function mutator () {
    // avoid leaking arguments: 避免泄露參數(shù) arguments
    // http://jsperf.com/closure-with-arguments
    var i = arguments.length
    var args = new Array(i)
    while (i--) {
      args[i] = arguments[i]
    }
    var result = original.apply(this, args)
    var ob = this.__ob__
    var inserted
    switch (method) {
      case "push":
        inserted = args
        break
      case "unshift":
        inserted = args
        break
      case "splice":
        inserted = args.slice(2)
        break
    }
    if (inserted) ob.observeArray(inserted)
    // notify change
    ob.dep.notify()
    return result
  })
})

通過改寫數(shù)組的幾個原型方法,從而能夠在開發(fā)者操作 data 數(shù)組時,能夠觸發(fā)更新事件: ob.dep.notify()

src/observer/index.js

index.js 實現(xiàn)了 Observer 類, 觀察者類綁定了每一個被觀察的對象,一旦綁定,Observer 類會將目標對象的屬性property keys 轉(zhuǎn)化為 getter/setters, 以收集依賴關(guān)系和分派更新

/**
 * Observer class that are attached to each observed
 * object. Once attached, the observer converts target
 * object"s property keys into getter/setters that
 * collect dependencies and dispatches updates.
 *
 * @param {Array|Object} value
 * @constructor
 */
export function Observer (value) {
  this.value = value
  this.dep = new Dep()
  def(value, "__ob__", this)
  if (isArray(value)) {
    var augment = hasProto
      ? protoAugment
      : copyAugment
    augment(value, arrayMethods, arrayKeys)
    this.observeArray(value)
  } else {
    this.walk(value)
  }
}
...

從構(gòu)造函數(shù)可以知道之前代碼里一直出現(xiàn)的 _ob_ 屬性就是指 Observer 類

其中 hasProto 實現(xiàn)在 util/env 中:

export const hasProto = "__proto__" in {}

實現(xiàn)的原理是利用 Object 的 Geeter 和 Setter:

/**
 * Define a reactive property on an Object.
 *
 * @param {Object} obj
 * @param {String} key
 * @param {*} val
 */

export function defineReactive (obj, key, val) {
  var dep = new Dep()

  // cater for pre-defined getter/setters
  var getter, setter
  if (config.convertAllProperties) {
    var property = Object.getOwnPropertyDescriptor(obj, key)
    if (property && property.configurable === false) {
      return
    }
    getter = property && property.get
    setter = property && property.set
  }

  var childOb = 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 (isArray(value)) {
          for (var e, i = 0, l = value.length; i < l; i++) {
            e = value[i]
            e && e.__ob__ && e.__ob__.dep.depend()
          }
        }
      }
      return value
    },
    set: function reactiveSetter (newVal) {
      var value = getter ? getter.call(obj) : val
      if (newVal === value) {
        return
      }
      if (setter) {
        setter.call(obj, newVal)
      } else {
        val = newVal
      }
      childOb = observe(newVal)
      dep.notify()
    }
  })
}

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

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

相關(guān)文章

  • 從Vue.js源碼角度再看數(shù)據(jù)綁定

    摘要:在學(xué)習(xí)過程中,為加上了中文的注釋,希望可以對其他想學(xué)習(xí)源碼的小伙伴有所幫助。數(shù)據(jù)綁定原理前面已經(jīng)講過數(shù)據(jù)綁定的原理了,現(xiàn)在從源碼來看一下數(shù)據(jù)綁定在中是如何實現(xiàn)的。 寫在前面 因為對Vue.js很感興趣,而且平時工作的技術(shù)棧也是Vue.js,這幾個月花了些時間研究學(xué)習(xí)了一下Vue.js源碼,并做了總結(jié)與輸出。文章的原地址:https://github.com/answershuto/le...

    elina 評論0 收藏0
  • VueJS源碼學(xué)習(xí)——MutationObserver實現(xiàn)nextTick

    摘要:倡導(dǎo)開發(fā)者盡量不直接操作,但有的時候由于各種需求讓開發(fā)者不得不這樣做,于是的實現(xiàn)就是讓開發(fā)者在修改數(shù)據(jù)后,能夠在數(shù)據(jù)更新到后才執(zhí)行對應(yīng)的函數(shù),從而獲取最新的數(shù)據(jù)。 Vue 倡導(dǎo)開發(fā)者盡量不直接操作 DOM,但有的時候由于各種需求讓開發(fā)者不得不這樣做,于是 nextTick 的實現(xiàn)就是讓開發(fā)者在修改數(shù)據(jù)后,能夠在數(shù)據(jù)更新到 DOM 后才執(zhí)行對應(yīng)的函數(shù),從而獲取最新的 DON 數(shù)據(jù)。 原文...

    xumenger 評論0 收藏0
  • VueJS源碼學(xué)習(xí)——項目結(jié)構(gòu)&目錄

    摘要:所以整個的核心,就是如何實現(xiàn)這三樣?xùn)|西以上摘自囧克斯博客的一篇文章從版本開始這個時候的項目結(jié)構(gòu)如下源碼在里面,為打包編譯的代碼,為打包后代碼放置的位置,為測試代碼目錄。節(jié)點類型摘自資源另一位作者關(guān)于源碼解析 本項目的源碼學(xué)習(xí)筆記是基于 Vue 1.0.9 版本的也就是最早的 tag 版本,之所以選擇這個版本,是因為這個是最原始沒有太多功能拓展的版本,有利于更好的看到 Vue 最開始的骨...

    ad6623 評論0 收藏0
  • RxJava2.x源碼解析(一):訂閱流程

    摘要:現(xiàn)在網(wǎng)上已經(jīng)有大量的源碼分析文章,各種技術(shù)的都有。你完全可以寫成下面的鏈式風(fēng)格方法會最先被執(zhí)行同樣,為了便于理解,我會借用流里面經(jīng)常用到的水流進行類比。該子類的命名是有規(guī)律可言的?,F(xiàn)在網(wǎng)上已經(jīng)有大量的源碼分析文章,各種技術(shù)的都有。但我覺得很多文章對初學(xué)者并不友好,讓人讀起來云里霧里的,比源碼還源碼。究其原因,是根本沒有從學(xué)習(xí)者的角度去分析。在自己完成了源碼閱讀之后,卻忘記了自己是如何一步步提...

    harryhappy 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<