摘要:那后面的部分就容易理解了,使用方法提交。返回的是刪除的。然后為定義屬性設置為表示可枚舉。前存儲先前的設置為是用于取消所有的警告和提醒。這樣工程量實在是太多了,下次的源碼分析將會以我總結的方式來學習源碼
繼上面講完contructor函數,我們繼續來講后面的內容
</>復制代碼
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里邊的語法,get語法是將對象屬性綁定到查詢該屬性時將被調用的函數,而set語法是查詢對象屬性將被調用的函數。當state屬性發生變化時,就會返回state的值,set用于檢測在我們設置state的時候是否是生產環境,如果不是生產環境,就進行斷點。
</>復制代碼
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函數接受三個參數,_type表示mutaion的類型,_payload表示額外的參數,options表示一些配置。在函數中有函數叫unfyObjectStyle(),來看看他的代碼
</>復制代碼
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 }
}
這個函數很簡單,就是在type為對象的情況下,對傳進來的參數進行各自獲取。繼續看commit函數,根據unifyObjectStyle()處理后的type去找到mutations,withCommient的代碼如下
</>復制代碼
_withCommit (fn) {
const committing = this._committing
this._committing = true
fn()
this._committing = committing
}
這個函數最重要的部分在于設置this._committing = true為什么這么做呢。是因為我們在觀測state的狀態的時候,我們可以通過看this._commiting的值來確定state修改是否錯誤,如果為false那么是不是狀態修改就出現了問題呢。
那commit后面的部分就容易理解了,使用this._withCommit方法提交mutation。
this._subscribers是什么內容呢,這在我們上一篇提過是用來存儲所有對 mutation 變化的訂閱者。遍歷this._subscribers進行回調。
</>復制代碼
options && options.silent
這兒我也不太懂黃軼老師說的是靜默模式:靜默模式就是用戶不干擾的情況下,計算機自我處理的情況。
下面是是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函數非常相似,取值,然后找到對應action。
this._actionSubscribers
跟前面commit方法不同的是最后用的是這段代碼:
</>復制代碼
return entry.length > 1
? Promise.all(entry.map(handler => handler(payload)))
: entry[0](payload)
如果獲取到的action的數量不止一個那么就進行Promise.all()遍歷每個action進行回調函數回調,前幾天看到一道面試題如果一個進程需要消耗8s,
另外一個進程需要消耗3秒,如何才能讓兩個進行的時間最短,解決方法就是Promise.all([a,b])注意里邊的必須是一個數組,這樣才能讓兩個進程同時進行。如果長度為1,則調用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)
}
}
}
來看看genericSubscribe都做了什么,接受兩個參數,就是對subs進行調整,如果subs里邊沒有fn,那么向subs.push(fn)。返回的是刪除fn的subs。那么上面subscribe和subscribeAction就是對傳入的fn然后經過
genericSubscribe()函數進行處理
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作用是響應式的檢測一個getter方法的返回值,當值反生變化的時候,發生回調。
函數首先首先斷言watch的getter必須是一個方法,接著利用了vue的實例對象的this._watcherVM的watch方法
</>復制代碼
replaceState (state) {
this._withCommit(() => {
this._vm._data.$$state = state
})
}
用于修改state,調用 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)
}
字面意思能看出動態注冊Module的意思,動態的意思是什么呢。就是有些異步操作,我們需要使用這個函數就能夠動態注冊module了。
這兒有一個函數resetStoreVM,我們來看看他的實現方式
</>復制代碼
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())
}
}
這個函數的意思在于監聽數據的變化,首先進行store.getters的初始化。forEachValue循環所有處理過的getters,并且新建computed對象進行存儲,通過Object.defineProperty。然后為store.getter定義屬性key,enumerable設置為true,表示可枚舉。
前存儲先前的Vue.config.slient,Vue.config.slient 設置為true是用于取消所有的警告和提醒。
</>復制代碼
store._vm = new Vue({
data: {
$$state: state
},
computed
})
這個就很簡單了,創建一個Vue的實例,然后把state放到data里邊去,computed里邊的值用getters填充。
</>復制代碼
if (store.strict) {
enableStrictMode(store)
}
如果是嚴格模式的話,則調用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 })
}
這個函數做了什么了,看assert寫的意識就是,如果設置了嚴格模式,就不允許用戶在mutaion以外的方式進行修改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為True的時候,將原有的vm中的state設置為空,所有原來的getters都會重新計算一遍,為什么會這樣呢,這在前面我們創建一個vue的實例的時候,將getters作為了computed,我們知道在Vue中,值一旦發生變化,那么computed就會重新變化。
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)
}
跟函數registerModule相似,用于動態卸載module。講講這里的this._withCommit的作用,
把當前的模塊的state對象從父state上刪除,最后調用resetStore函數,下面是resetStore函數
</>復制代碼
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)
}
這個方法的作用就是重置store, installModule就是重新安裝_aciton,_mutations,_wrappedGetters這些屬性,resetStoreVM然后重置store的_vm對象。
</>復制代碼
hotUpdate (newOptions) {
this._modules.update(newOptions)
resetStore(this, true)
}
函數的作用就是熱加載新的action和mutation。先更新modules,然后更新Store。
vuex里邊最重要的class Store就講完了。我們在講講其他重要的函數。
</>復制代碼
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
}
這個函數的原理就是構造一個新的對象,遍歷原對象或者數組,遞歸調用deepCopy。這兒加了一個cache,為什么呢。這是為了提高性能,比如說在Facinaciate中,我們就可以使用這種方法來提高性能,不用每計算一次,又重新計算已經計算過的東西
這次就講到這里,下次再講其他重要的函數
下次我決定不采用這種什么函數都講清楚的方式了。這樣工程量實在是太多了,下次的源碼分析將會以我總結的方式來學習源碼
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/89458.html
摘要:那后面的部分就容易理解了,使用方法提交。返回的是刪除的。然后為定義屬性設置為表示可枚舉。前存儲先前的設置為是用于取消所有的警告和提醒。這樣工程量實在是太多了,下次的源碼分析將會以我總結的方式來學習源碼 繼上面講完contructor函數,我們繼續來講后面的內容 get state () { return this._vm._data.$$state } set state (...
摘要:提供了函數,它把直接映射到我們的組件中,先給出的使用值為值為讓我們看看的源碼實現規范當前的命名空間。在中,都是同步事務。同步的意義在于這樣每一個執行完成后都可以對應到一個新的狀態和一樣,這樣就可以打個存下來,然后就可以隨便了。 Vue 組件中獲得 Vuex 狀態 按官網說法:由于 Vuex 的狀態存儲是響應式的,從 store 實例中讀取狀態最簡單的方法就是在計算屬性中返回某個狀態,本...
摘要:五六月份推薦集合查看最新的請點擊集前端最近很火的框架資源定時更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風荷舉。家住吳門,久作長安旅。五月漁郎相憶否。小楫輕舟,夢入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請::點擊::集web前端最近很火的vue2框架資源;定時更新,歡迎 Star 一下。 蘇...
閱讀 1316·2023-04-26 03:05
閱讀 773·2021-10-19 11:43
閱讀 3219·2021-09-26 09:55
閱讀 829·2019-08-30 15:56
閱讀 986·2019-08-30 15:44
閱讀 1240·2019-08-30 15:44
閱讀 2723·2019-08-30 14:23
閱讀 3237·2019-08-30 13:13