摘要:給的實例注入一個的屬性,這也就是為什么我們在的組件中可以通過訪問到的各種數據和狀態源碼位置,是怎么實現的源碼位置是對的的初始化,它接受個參數,為當前實例,為的,為執行的回調函數,為當前模塊的路徑。
20190221
請簡述一下vuex實現原理
對vuex基礎概念有不懂的可以點這里
vuex實現原理我們簡單過一遍源碼 地址 https://github.com/vuejs/vuex
首先我們例出幾個問題進行思考
store是怎么注冊的?
mutation,commit 是怎么實現的?
輔助函數是怎么實現的?
store是怎么注冊的看了下面的源碼就很清楚了, 我們看到vuex在vue 的生命周期中的初始化鉤子前插入一段 Vuex 初始化代碼。給 Vue 的實例注入一個 $store 的屬性,這也就是為什么我們在 Vue 的組件中可以通過 this.$store.xxx 訪問到 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 } } }mutations,commit 是怎么實現的
// 源碼位置 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的定義
// 源碼位置 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 注冊的回調函數
輔助函數輔助函數的實現都差不太多,這里只講解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的效果
computed: mapState({ name: state => state.name, }) // 等同于 computed: { name: this.$store.state.name }關于JS每日一題
JS每日一題可以看成是一個語音答題社區
每天利用碎片時間采用60秒內的語音形式來完成當天的考題
群主在次日0點推送當天的參考答案
注 絕不僅限于完成當天任務,更多是查漏補缺,學習群內其它同學優秀的答題思路
點擊加入答題
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/102015.html
摘要:問簡述一下的編譯過程先上一張圖大致看一下整個流程從上圖中我們可以看到是從后開始進行中整體邏輯分為三個部分解析器將模板字符串轉換成優化器對進行靜態節點標記,主要用來做虛擬的渲染優化代碼生成器使用生成函數代碼字符串開始前先解釋一下抽象 20190215問 簡述一下Vue.js的template編譯過程? 先上一張圖大致看一下整個流程showImg(https://image-static....
摘要:什么情況下適合使合使用中有幾個步驟開始之前先簡單了解一下定義是一個狀態管理機制采用集中式存儲應用所有組件的狀態嗯,就是一句話能說明白的,沒明白的,我們用代碼再理解一下什么叫集中式式存儲比如下面這段代碼,同時需要用到,那么我們首先能想到就是在 20190121 什么情況下適合使合vuex?Vuex使用中有幾個步驟? 開始之前先簡單了解一下vuex 定義: vuex是一個狀態管理機制,采用...
閱讀 569·2023-04-26 02:58
閱讀 2309·2021-09-27 14:01
閱讀 3616·2021-09-22 15:57
閱讀 1175·2019-08-30 15:56
閱讀 1049·2019-08-30 15:53
閱讀 796·2019-08-30 15:52
閱讀 651·2019-08-26 14:01
閱讀 2167·2019-08-26 13:41