摘要:那后面的部分就容易理解了,使用方法提交。返回的是刪除的。然后為定義屬性設(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
registerModuleregisterModule (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ì)重新變化。
unregisterModuleunregisterModule (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
摘要:那后面的部分就容易理解了,使用方法提交。返回的是刪除的。然后為定義屬性設(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 (...
摘要:提供了函數(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),本...
摘要:五六月份推薦集合查看最新的請(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 一下。 蘇...
閱讀 955·2019-08-30 14:24
閱讀 987·2019-08-30 14:13
閱讀 1799·2019-08-29 17:21
閱讀 2661·2019-08-29 13:44
閱讀 1654·2019-08-29 11:04
閱讀 438·2019-08-26 10:44
閱讀 2564·2019-08-23 14:04
閱讀 908·2019-08-23 12:08