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

資訊專欄INFORMATION COLUMN

vuex源碼分析(二)

fizz / 1333人閱讀

摘要:那后面的部分就容易理解了,使用方法提交。返回的是刪除的。然后為定義屬性設(shè)置為表示可枚舉。前存儲(chǔ)先前的設(shè)置為是用于取消所有的警告和提醒。這樣工程量實(shí)在是太多了,下次的源碼分析將會(huì)以我總結(jié)的方式來(lái)學(xué)習(xí)源碼

繼上面講完contructor函數(shù),我們繼續(xù)來(lái)講后面的內(nèi)容

get state () {
    return this._vm._data.$$state
}

set state (v) {
    if (process.env.NODE_ENV !== "production") {
          assert(false, `Use store.replaceState() to explicit replace store state.`)
    }
}

get和set方法都有es6里邊的語(yǔ)法,get語(yǔ)法是將對(duì)象屬性綁定到查詢?cè)搶傩詴r(shí)將被調(diào)用的函數(shù),而set語(yǔ)法是查詢對(duì)象屬性將被調(diào)用的函數(shù)。當(dāng)state屬性發(fā)生變化時(shí),就會(huì)返回state的值,set用于檢測(cè)在我們?cè)O(shè)置state的時(shí)候是否是生產(chǎn)環(huán)境,如果不是生產(chǎn)環(huán)境,就進(jìn)行斷點(diǎn)。

commit (_type, _payload, _options) {
    // check object-style commit
    const {
      type,
      payload,
      options
    } = unifyObjectStyle(_type, _payload, _options)

    const mutation = { type, payload }
    const entry = this._mutations[type]
    if (!entry) {
      if (process.env.NODE_ENV !== "production") {
        console.error(`[vuex] unknown mutation type: ${type}`)
      }
      return
    }
    this._withCommit(() => {
      entry.forEach(function commitIterator (handler) {
        handler(payload)
      })
    })
    this._subscribers.forEach(sub => sub(mutation, this.state))

    if (
      process.env.NODE_ENV !== "production" &&
      options && options.silent
    ) {
      console.warn(
        `[vuex] mutation type: ${type}. Silent option has been removed. ` +
        "Use the filter functionality in the vue-devtools"
      )
    }
}

commit函數(shù)接受三個(gè)參數(shù),_type表示mutaion的類(lèi)型,_payload表示額外的參數(shù),options表示一些配置。在函數(shù)中有函數(shù)叫unfyObjectStyle(),來(lái)看看他的代碼

function unifyObjectStyle (type, payload, options) {
  if (isObject(type) && type.type) {
    options = payload
    payload = type
    type = type.type
  }

  if (process.env.NODE_ENV !== "production") {
    assert(typeof type === "string", `Expects string as the type, but found ${typeof type}.`)
  }

  return { type, payload, options }
}

這個(gè)函數(shù)很簡(jiǎn)單,就是在type為對(duì)象的情況下,對(duì)傳進(jìn)來(lái)的參數(shù)進(jìn)行各自獲取。繼續(xù)看commit函數(shù),根據(jù)unifyObjectStyle()處理后的type去找到mutations,withCommient的代碼如下

_withCommit (fn) {
    const committing = this._committing
    this._committing = true
    fn()
    this._committing = committing
}

這個(gè)函數(shù)最重要的部分在于設(shè)置this._committing = true為什么這么做呢。是因?yàn)槲覀冊(cè)谟^測(cè)state的狀態(tài)的時(shí)候,我們可以通過(guò)看this._commiting的值來(lái)確定state修改是否錯(cuò)誤,如果為false那么是不是狀態(tài)修改就出現(xiàn)了問(wèn)題呢。
那commit后面的部分就容易理解了,使用this._withCommit方法提交mutation。
this._subscribers是什么內(nèi)容呢,這在我們上一篇提過(guò)是用來(lái)存儲(chǔ)所有對(duì) mutation 變化的訂閱者。遍歷this._subscribers進(jìn)行回調(diào)。

options && options.silent

這兒我也不太懂黃軼老師說(shuō)的是靜默模式:靜默模式就是用戶不干擾的情況下,計(jì)算機(jī)自我處理的情況。
下面是是dispatch的代碼

dispatch (_type, _payload) {
    // check object-style dispatch
    const {
      type,
      payload
    } = unifyObjectStyle(_type, _payload)

    const action = { type, payload }
    const entry = this._actions[type]
    if (!entry) {
      if (process.env.NODE_ENV !== "production") {
        console.error(`[vuex] unknown action type: ${type}`)
      }
      return
    }

    this._actionSubscribers.forEach(sub => sub(action, this.state))

    return entry.length > 1
      ? Promise.all(entry.map(handler => handler(payload)))
      : entry[0](payload)
  }

前面幾行代碼跟commit函數(shù)非常相似,取值,然后找到對(duì)應(yīng)action。

this._actionSubscribers
跟前面commit方法不同的是最后用的是這段代碼:

return entry.length > 1
      ? Promise.all(entry.map(handler => handler(payload)))
      : entry[0](payload)

如果獲取到的action的數(shù)量不止一個(gè)那么就進(jìn)行Promise.all()遍歷每個(gè)action進(jìn)行回調(diào)函數(shù)回調(diào),前幾天看到一道面試題如果一個(gè)進(jìn)程需要消耗8s,
另外一個(gè)進(jìn)程需要消耗3秒,如何才能讓兩個(gè)進(jìn)行的時(shí)間最短,解決方法就是Promise.all([a,b])注意里邊的必須是一個(gè)數(shù)組,這樣才能讓兩個(gè)進(jìn)程同時(shí)進(jìn)行。如果長(zhǎng)度為1,則調(diào)用entry0

 subscribe (fn) {
    return genericSubscribe(fn, this._subscribers)
 }

 subscribeAction (fn) {
    return genericSubscribe(fn, this._actionSubscribers)
 }
 function genericSubscribe (fn, subs) {
  if (subs.indexOf(fn) < 0) {
    subs.push(fn)
  }
  return () => {
    const i = subs.indexOf(fn)
    if (i > -1) {
      subs.splice(i, 1)
    }
  }
}

來(lái)看看genericSubscribe都做了什么,接受兩個(gè)參數(shù),就是對(duì)subs進(jìn)行調(diào)整,如果subs里邊沒(méi)有fn,那么向subs.push(fn)。返回的是刪除fn的subs。那么上面subscribe和subscribeAction就是對(duì)傳入的fn然后經(jīng)過(guò)
genericSubscribe()函數(shù)進(jìn)行處理
watch (getter, cb, options) {

if (process.env.NODE_ENV !== "production") {
      assert(typeof getter === "function", `store.watch only accepts a function.`)
}
    return this._watcherVM.$watch(() => getter(this.state, this.getters), cb, options)

}
watch作用是響應(yīng)式的檢測(cè)一個(gè)getter方法的返回值,當(dāng)值反生變化的時(shí)候,發(fā)生回調(diào)。
函數(shù)首先首先斷言watch的getter必須是一個(gè)方法,接著利用了vue的實(shí)例對(duì)象的this._watcherVM的watch方法

replaceState (state) {
    this._withCommit(() => {
          this._vm._data.$$state = state
    })
}

用于修改state,調(diào)用 this._withCommit 方法修改 Store 的 rootState

registerModule
registerModule (path, rawModule, options = {}) {
    if (typeof path === "string") path = [path]

    if (process.env.NODE_ENV !== "production") {
      assert(Array.isArray(path), `module path must be a string or an Array.`)
      assert(path.length > 0, "cannot register the root module by using registerModule.")
    }

    this._modules.register(path, rawModule)
    installModule(this, this.state, path, this._modules.get(path), options.preserveState)
    // reset store to update getters...
    resetStoreVM(this, this.state)
}

字面意思能看出動(dòng)態(tài)注冊(cè)Module的意思,動(dòng)態(tài)的意思是什么呢。就是有些異步操作,我們需要使用這個(gè)函數(shù)就能夠動(dòng)態(tài)注冊(cè)module了。
這兒有一個(gè)函數(shù)resetStoreVM,我們來(lái)看看他的實(shí)現(xiàn)方式

function resetStoreVM (store, state, hot) {
  const oldVm = store._vm

  // bind store public getters
  store.getters = {}
  const wrappedGetters = store._wrappedGetters
  const computed = {}
  forEachValue(wrappedGetters, (fn, key) => {
    // use computed to leverage its lazy-caching mechanism
    computed[key] = () => fn(store)
    Object.defineProperty(store.getters, key, {
      get: () => store._vm[key],
      enumerable: true // for local getters
    })
  })

  // use a Vue instance to store the state tree
  // suppress warnings just in case the user has added
  // some funky global mixins
  const silent = Vue.config.silent
  Vue.config.silent = true
  store._vm = new Vue({
    data: {
      $$state: state
    },
    computed
  })
  Vue.config.silent = silent

  // enable strict mode for new vm
  if (store.strict) {
    enableStrictMode(store)
  }

  if (oldVm) {
    if (hot) {
      // dispatch changes in all subscribed watchers
      // to force getter re-evaluation for hot reloading.
      store._withCommit(() => {
        oldVm._data.$$state = null
      })
    }
    Vue.nextTick(() => oldVm.$destroy())
  }
}

這個(gè)函數(shù)的意思在于監(jiān)聽(tīng)數(shù)據(jù)的變化,首先進(jìn)行store.getters的初始化。forEachValue循環(huán)所有處理過(guò)的getters,并且新建computed對(duì)象進(jìn)行存儲(chǔ),通過(guò)Object.defineProperty。然后為store.getter定義屬性key,enumerable設(shè)置為true,表示可枚舉。
前存儲(chǔ)先前的Vue.config.slient,Vue.config.slient 設(shè)置為true是用于取消所有的警告和提醒。

store._vm = new Vue({
    data: {
        $$state: state
    },
    computed
})

這個(gè)就很簡(jiǎn)單了,創(chuàng)建一個(gè)Vue的實(shí)例,然后把state放到data里邊去,computed里邊的值用getters填充。

 if (store.strict) {
    enableStrictMode(store)
  }

如果是嚴(yán)格模式的話,則調(diào)用enableStrictMode()
下面是enableStrictMode的代碼

 function enableStrictMode (store) {
  store._vm.$watch(function () { return this._data.$$state }, () => {
    if (process.env.NODE_ENV !== "production") {
      assert(store._committing, `Do not mutate vuex store state outside mutation handlers.`)
    }
  }, { deep: true, sync: true })
}

這個(gè)函數(shù)做了什么了,看assert寫(xiě)的意識(shí)就是,如果設(shè)置了嚴(yán)格模式,就不允許用戶在mutaion以外的方式進(jìn)行修改state

if (oldVm) {
    if (hot) {
      // dispatch changes in all subscribed watchers
      // to force getter re-evaluation for hot reloading.
      store._withCommit(() => {
        oldVm._data.$$state = null
      })
    }
    Vue.nextTick(() => oldVm.$destroy())
}

如果oldVm存在,并且hot為T(mén)rue的時(shí)候,將原有的vm中的state設(shè)置為空,所有原來(lái)的getters都會(huì)重新計(jì)算一遍,為什么會(huì)這樣呢,這在前面我們創(chuàng)建一個(gè)vue的實(shí)例的時(shí)候,將getters作為了computed,我們知道在Vue中,值一旦發(fā)生變化,那么computed就會(huì)重新變化。

unregisterModule
unregisterModule (path) {
    if (typeof path === "string") path = [path]

    if (process.env.NODE_ENV !== "production") {
      assert(Array.isArray(path), `module path must be a string or an Array.`)
    }

    this._modules.unregister(path)
    this._withCommit(() => {
      const parentState = getNestedState(this.state, path.slice(0, -1))
      Vue.delete(parentState, path[path.length - 1])
    })
    resetStore(this)
}

跟函數(shù)registerModule相似,用于動(dòng)態(tài)卸載module。講講這里的this._withCommit的作用,
把當(dāng)前的模塊的state對(duì)象從父state上刪除,最后調(diào)用resetStore函數(shù),下面是resetStore函數(shù)

function resetStore (store, hot) {
  store._actions = Object.create(null)
  store._mutations = Object.create(null)
  store._wrappedGetters = Object.create(null)
  store._modulesNamespaceMap = Object.create(null)
  const state = store.state
  // init all modules
  installModule(store, state, [], store._modules.root, true)
  // reset vm
  resetStoreVM(store, state, hot)
}

這個(gè)方法的作用就是重置store, installModule就是重新安裝_aciton,_mutations,_wrappedGetters這些屬性,resetStoreVM然后重置store的_vm對(duì)象。

hotUpdate (newOptions) {
    this._modules.update(newOptions)
    resetStore(this, true)
}

函數(shù)的作用就是熱加載新的action和mutation。先更新modules,然后更新Store。
vuex里邊最重要的class Store就講完了。我們?cè)谥v講其他重要的函數(shù)。

export function deepCopy (obj, cache = []) {
  // just return if obj is immutable value
  if (obj === null || typeof obj !== "object") {
    return obj
  }

  // if obj is hit, it is in circular structure
  const hit = find(cache, c => c.original === obj)
  if (hit) {
    return hit.copy
  }

  const copy = Array.isArray(obj) ? [] : {}
  // put the copy into cache at first
  // because we want to refer it in recursive deepCopy
  cache.push({
    original: obj,
    copy
  })

  Object.keys(obj).forEach(key => {
    copy[key] = deepCopy(obj[key], cache)
  })

  return copy
}

這個(gè)函數(shù)的原理就是構(gòu)造一個(gè)新的對(duì)象,遍歷原對(duì)象或者數(shù)組,遞歸調(diào)用deepCopy。這兒加了一個(gè)cache,為什么呢。這是為了提高性能,比如說(shuō)在Facinaciate中,我們就可以使用這種方法來(lái)提高性能,不用每計(jì)算一次,又重新計(jì)算已經(jīng)計(jì)算過(guò)的東西
這次就講到這里,下次再講其他重要的函數(shù)

下次我決定不采用這種什么函數(shù)都講清楚的方式了。這樣工程量實(shí)在是太多了,下次的源碼分析將會(huì)以我總結(jié)的方式來(lái)學(xué)習(xí)源碼

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

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

相關(guān)文章

  • vuex源碼分析

    摘要:那后面的部分就容易理解了,使用方法提交。返回的是刪除的。然后為定義屬性設(shè)置為表示可枚舉。前存儲(chǔ)先前的設(shè)置為是用于取消所有的警告和提醒。這樣工程量實(shí)在是太多了,下次的源碼分析將會(huì)以我總結(jié)的方式來(lái)學(xué)習(xí)源碼 繼上面講完contructor函數(shù),我們繼續(xù)來(lái)講后面的內(nèi)容 get state () { return this._vm._data.$$state } set state (...

    jeffrey_up 評(píng)論0 收藏0
  • Vue源碼解析(五)-vuex

    摘要:提供了函數(shù),它把直接映射到我們的組件中,先給出的使用值為值為讓我們看看的源碼實(shí)現(xiàn)規(guī)范當(dāng)前的命名空間。在中,都是同步事務(wù)。同步的意義在于這樣每一個(gè)執(zhí)行完成后都可以對(duì)應(yīng)到一個(gè)新的狀態(tài)和一樣,這樣就可以打個(gè)存下來(lái),然后就可以隨便了。 Vue 組件中獲得 Vuex 狀態(tài) 按官網(wǎng)說(shuō)法:由于 Vuex 的狀態(tài)存儲(chǔ)是響應(yīng)式的,從 store 實(shí)例中讀取狀態(tài)最簡(jiǎn)單的方法就是在計(jì)算屬性中返回某個(gè)狀態(tài),本...

    calx 評(píng)論0 收藏0
  • 關(guān)于Vue2一些值得推薦的文章 -- 五、六月份

    摘要:五六月份推薦集合查看最新的請(qǐng)點(diǎn)擊集前端最近很火的框架資源定時(shí)更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥(niǎo)雀呼晴,侵曉窺檐語(yǔ)。葉上初陽(yáng)乾宿雨,水面清圓,一一風(fēng)荷舉。家住吳門(mén),久作長(zhǎng)安旅。五月漁郎相憶否。小楫輕舟,夢(mèng)入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請(qǐng)::點(diǎn)擊::集web前端最近很火的vue2框架資源;定時(shí)更新,歡迎 Star 一下。 蘇...

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

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

0條評(píng)論

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