摘要:給的實例注入一個的屬性,這也就是為什么我們在的組件中可以通過訪問到的各種數(shù)據(jù)和狀態(tài)源碼位置,是怎么實現(xiàn)的源碼位置是對的的初始化,它接受個參數(shù),為當(dāng)前實例,為的,為執(zhí)行的回調(diào)函數(shù),為當(dāng)前模塊的路徑。
20190221
請簡述一下vuex實現(xiàn)原理
對vuex基礎(chǔ)概念有不懂的可以點這里
vuex實現(xiàn)原理我們簡單過一遍源碼 地址 https://github.com/vuejs/vuex
首先我們例出幾個問題進(jìn)行思考
store是怎么注冊的?
mutation,commit 是怎么實現(xiàn)的?
輔助函數(shù)是怎么實現(xiàn)的?
store是怎么注冊的看了下面的源碼就很清楚了, 我們看到vuex在vue 的生命周期中的初始化鉤子前插入一段 Vuex 初始化代碼。給 Vue 的實例注入一個 $store 的屬性,這也就是為什么我們在 Vue 的組件中可以通過 this.$store.xxx 訪問到 Vuex 的各種數(shù)據(jù)和狀態(tài)
// 源碼位置 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 是怎么實現(xiàn)的
// 源碼位置 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 個參數(shù),store為當(dāng)前 Store 實例,type為 mutation 的 key,handler 為 mutation 執(zhí)行的回調(diào)函數(shù),path 為當(dāng)前模塊的路徑。mutation 的作用就是同步修改當(dāng)前模塊的 state ,函數(shù)首先通過 type 拿到對應(yīng)的 mutation 對象數(shù)組, 然后把一個 mutation 的包裝函數(shù) push 到這個數(shù)組中,這個函數(shù)接收一個參數(shù) payload,這個就是我們在定義 mutation 的時候接收的額外參數(shù)。這個函數(shù)執(zhí)行的時候會調(diào)用 mutation 的回調(diào)函數(shù),并通過 getNestedState(store.state, path) 方法得到當(dāng)前模塊的 state,和 playload 一起作為回調(diào)函數(shù)的參數(shù)
我們知道m(xù)utation是通過commit來觸發(fā)的,這里我們也來看一下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 個參數(shù),type 表示 mutation 的類型,payload 表示額外的參數(shù),根據(jù) type 去查找對應(yīng)的 mutation,如果找不到,則輸出一條錯誤信息,否則遍歷這個 type 對應(yīng)的 mutation 對象數(shù)組,執(zhí)行 handler(payload) 方法,這個方法就是之前定義的 wrappedMutationHandler(handler),執(zhí)行它就相當(dāng)于執(zhí)行了 registerMutation 注冊的回調(diào)函數(shù)
輔助函數(shù)輔助函數(shù)的實現(xiàn)都差不太多,這里只講解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在調(diào)用了 normalizeMap 函數(shù)后,把傳入的 states 轉(zhuǎn)換成由 {key, val} 對象構(gòu)成的數(shù)組,接著調(diào)用 forEach 方法遍歷這個數(shù)組,構(gòu)造一個新的對象,這個新對象每個元素都返回一個新的函數(shù) mappedState,函數(shù)對 val 的類型判斷,如果 val 是一個函數(shù),則直接調(diào)用這個 val 函數(shù),把當(dāng)前 store 上的 state 和 getters 作為參數(shù),返回值作為 mappedState 的返回值;否則直接把 this.$store.state[val] 作為 mappedState 的返回值
為了更直觀的理解,我們看下最終mapState的效果
computed: mapState({ name: state => state.name, }) // 等同于 computed: { name: this.$store.state.name }關(guān)于JS每日一題
JS每日一題可以看成是一個語音答題社區(qū)
每天利用碎片時間采用60秒內(nèi)的語音形式來完成當(dāng)天的考題
群主在次日0點推送當(dāng)天的參考答案
注 絕不僅限于完成當(dāng)天任務(wù),更多是查漏補缺,學(xué)習(xí)群內(nèi)其它同學(xué)優(yōu)秀的答題思路
點擊加入答題
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/102015.html
摘要:問簡述一下的編譯過程先上一張圖大致看一下整個流程從上圖中我們可以看到是從后開始進(jìn)行中整體邏輯分為三個部分解析器將模板字符串轉(zhuǎn)換成優(yōu)化器對進(jìn)行靜態(tài)節(jié)點標(biāo)記,主要用來做虛擬的渲染優(yōu)化代碼生成器使用生成函數(shù)代碼字符串開始前先解釋一下抽象 20190215問 簡述一下Vue.js的template編譯過程? 先上一張圖大致看一下整個流程showImg(https://image-static....
摘要:什么情況下適合使合使用中有幾個步驟開始之前先簡單了解一下定義是一個狀態(tài)管理機(jī)制采用集中式存儲應(yīng)用所有組件的狀態(tài)嗯,就是一句話能說明白的,沒明白的,我們用代碼再理解一下什么叫集中式式存儲比如下面這段代碼,同時需要用到,那么我們首先能想到就是在 20190121 什么情況下適合使合vuex?Vuex使用中有幾個步驟? 開始之前先簡單了解一下vuex 定義: vuex是一個狀態(tài)管理機(jī)制,采用...
閱讀 561·2023-04-26 02:58
閱讀 2301·2021-09-27 14:01
閱讀 3605·2021-09-22 15:57
閱讀 1168·2019-08-30 15:56
閱讀 1043·2019-08-30 15:53
閱讀 787·2019-08-30 15:52
閱讀 645·2019-08-26 14:01
閱讀 2157·2019-08-26 13:41