請簡述一下vuex實現原理vue
對vuex基礎概念有不懂的能夠點 這裏
vuex實現原理咱們簡單過一遍源碼 地址 https://github.com/vuejs/vuexgit
首先咱們例出幾個問題進行思考github
看了下面的源碼就很清楚了, 咱們看到vuex在vue 的生命週期中的初始化鉤子前插入一段 Vuex 初始化代碼。給 Vue 的實例注入一個 $store
的屬性,這也就是爲何咱們在 Vue 的組件中能夠經過 this.$store.xxx
訪問到 Vuex 的各類數據和狀態vuex
// 源碼位置 https://github.com/vuejs/vuex/blob/665455f8daf8512e7adbf63c2842bc0b1e39efdb/src/mixin.js export default function (Vue) { const version = Number(Vue.version.split('.')[0]) if (version >= 2) { Vue.mixin({ beforeCreate: vuexInit }) } else { // override init and inject vuex init procedure // for 1.x backwards compatibility. const _init = Vue.prototype._init Vue.prototype._init = function (options = {}) { options.init = options.init ? [vuexInit].concat(options.init) : vuexInit _init.call(this, options) } } /** * Vuex init hook, injected into each instances init hooks list. */ function vuexInit () { const options = this.$options // store injection if (options.store) { this.$store = typeof options.store === 'function' ? options.store() : options.store } else if (options.parent && options.parent.$store) { this.$store = options.parent.$store } } }
// 源碼位置 https://github.com/vuejs/vuex/blob/665455f8daf8512e7adbf63c2842bc0b1e39efdb/src/store.js#L417 function registerMutation (store, type, handler, path = []) { const entry = store._mutations[type] || (store._mutations[type] = []) entry.push(function wrappedMutationHandler (payload) { handler(getNestedState(store.state, path), payload) }) }
registerMutation 是對 store 的 mutation 的初始化,它接受 4 個參數,store爲當前 Store 實例,type爲 mutation 的 key,handler 爲 mutation 執行的回調函數,path 爲當前模塊的路徑。mutation 的做用就是同步修改當前模塊的 state ,函數首先經過 type 拿到對應的 mutation 對象數組, 而後把一個 mutation 的包裝函數 push 到這個數組中,這個函數接收一個參數 payload,這個就是咱們在定義 mutation 的時候接收的額外參數。這個函數執行的時候會調用 mutation 的回調函數,並經過 getNestedState(store.state, path) 方法獲得當前模塊的 state,和 playload 一塊兒做爲回調函數的參數數組
咱們知道mutation是經過commit來觸發的,這裏咱們也來看一下commit的定義app
// 源碼位置 https://github.com/vuejs/vuex/blob/665455f8daf8512e7adbf63c2842bc0b1e39efdb/src/store.js#L82 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 支持 3 個參數,type 表示 mutation 的類型,payload 表示額外的參數,根據 type 去查找對應的 mutation,若是找不到,則輸出一條錯誤信息,不然遍歷這個 type 對應的 mutation 對象數組,執行 handler(payload) 方法,這個方法就是以前定義的 wrappedMutationHandler(handler),執行它就至關於執行了 registerMutation 註冊的回調函數ide
輔助函數的實現都差不太多,這裏只講解mapState函數
// 源碼地址 https://github.com/vuejs/vuex/blob/665455f8daf8512e7adbf63c2842bc0b1e39efdb/src/helpers.js#L7 export const mapState = normalizeNamespace((namespace, states) => { const res = {} normalizeMap(states).forEach(({ key, val }) => { res[key] = function mappedState () { let state = this.$store.state let getters = this.$store.getters if (namespace) { const module = getModuleByNamespace(this.$store, 'mapState', namespace) if (!module) { return } state = module.context.state getters = module.context.getters } return typeof val === 'function' ? val.call(this, state, getters) : state[val] } // mark vuex getter for devtools res[key].vuex = true }) return res })
mapState在調用了 normalizeMap 函數後,把傳入的 states 轉換成由 {key, val} 對象構成的數組,接着調用 forEach 方法遍歷這個數組,構造一個新的對象,這個新對象每一個元素都返回一個新的函數 mappedState,函數對 val 的類型判斷,若是 val 是一個函數,則直接調用這個 val 函數,把當前 store 上的 state 和 getters 做爲參數,返回值做爲 mappedState 的返回值;不然直接把 this.$store.state[val]
做爲 mappedState 的返回值學習
爲了更直觀的理解,咱們看下最終mapState的效果this
computed: mapState({ name: state => state.name, }) // 等同於 computed: { name: this.$store.state.name }
JS每日一題能夠當作是一個語音答題社區
天天利用碎片時間採用60秒內的語音形式來完成當天的考題
羣主在第二天0點推送當天的參考答案