摘要:而鉆研最好的方式,就是閱讀的源代碼。整個的源代碼,核心內(nèi)容包括兩部分。逃而動手腳的代碼,就存在于源代碼的中。整個源代碼讀下來一遍,雖然有些部分不太理解,但是對和一些代碼的使用的理解又加深了一步。
起因筆記中的Vue與Vuex版本為1.0.21和0.6.2,需要閱讀者有使用Vue,Vuex,ES6的經(jīng)驗。
俗話說得好,沒有無緣無故的愛,也沒有無緣無故的恨,更不會無緣無故的去閱讀別人的源代碼。
之所以會去閱讀Vuex的源代碼,是因為在剛開始接觸Vuex時,就在官方文檔的Actions部分,看到這么一句:
// the simplest action function increment (store) { store.dispatch("INCREMENT") } // a action with additional arguments // with ES2015 argument destructuring function incrementBy ({ dispatch }, amount) { dispatch("INCREMENT", amount) }
上面的Action還好說,能看懂,但是下面使用ES6寫法的Action是什么鬼呀喂(摔?。?br>雖然知道有解構(gòu)賦值,但是那個{ dispatch }又是從哪兒冒出來的呀喂!明明我在調(diào)用時,沒有傳這個參數(shù)呀!
之前因為趕項目進(jìn)度,所以抱著能用就行的態(tài)度,也就沒管那么多。如今有了空閑時間,必須好好鉆研一下呀。
而鉆研最好的方式,就是閱讀Vuex的源代碼。這樣就能弄清楚,那個{ dispatch }到底從哪兒冒出來的。
Vuex的源代碼量挺少的,加起來也才600行不到,但是其中大量使用了ES6的語法,且部分功能(如Vuex初始化)使用到了Vue。所以讀起來還是有些費(fèi)勁的。
整個Vuex的源代碼,核心內(nèi)容包括兩部分。一部分是Store的構(gòu)造函數(shù),另一部分則是Vuex的初始化函數(shù)。
而剛才問題的答案,就在第二部分。
首先要介紹的,就是Vuex在Vue項目中的初始化。這兒貼一段代碼:
首先是Vuex中,我寫的Actions源代碼:
// global/Vuex/action.js export const getMe = ({ dispatch }) => { /** * 異步操作,獲取用戶信息,并存入Vuex的state中 */ res.user.get_me() .then(data => { dispatch("GET_ME", data) }) .catch(err => { console.log(err) }) }
這個則是頂層組件,調(diào)用store的地方。由于Vuex的特點(diǎn),store只需要在最頂層的組件聲明一次。
接下來則是組件中,則是實際調(diào)用Vuex的代碼。
// index.vue import { getMe } from "./../global/Vuex/action" export default { vuex: { actions: { getMe }, getters: { // 從state中獲取信息 user: state => state.user } }, ready() { // 開始獲取用戶信息 this.getMe() } }
在這兒,可以很明顯的看出,我在使用this.getMe()時,是沒有任何參數(shù)的。但是在getMe函數(shù)的定義中,是需要解構(gòu)賦值出{dispatch}的。
就好比說這個:
function getX({ x }) { console.log(x) } getX({ x: 3, y: 5 }) // 3
你得傳入相應(yīng)的參數(shù),才能進(jìn)行解構(gòu)賦值。
同時,我注意到在Vuex的Actions調(diào)用,需要在Vue的options的Vuex.actions中先聲明,之后才能使用。
那么,一定是Vuex對這個Action動了手腳。(逃)
而動手腳的代碼,就存在于Vuex源代碼的override.js中。這個文件,是用于初始化Vuex的。
在override.js中,有個vuexInit的函數(shù)??疵志椭?,這是拿來初始化Vuex的。
在代碼開頭,有這么一句:
const options = this.$options const { store, vuex } = options // 感覺解構(gòu)賦值真的很棒,這樣寫能省很多時間。 // 下面的是老寫法 // const store = options.store // const vuex = options.vuex
在這兒,用于是在Vue中調(diào)用,所以this指向Vue,而this.$options則是Vue的配置項。
也就是寫Vue組件時的:
export default {……一些配置}
這里,就把Vue配置項的store和vuex抽離出來了。
接下來,則看到了Vuex源代碼的精妙之處:
// store injection if (store) { this.$store = store } else if (options.parent && options.parent.$store) { this.$store = options.parent.$store }
解構(gòu)賦值并不是一定成功的,如果store在options中不存在,那么store就會是undefined。但是我們需要找store。
于是Vuex提供了向父級(Vue中的功能)尋找store的功能。不難看出,這兒父級的$store如果不存在,那么其實他也會到自己的父級去尋找。直到找到為止。
就想一條鎖鏈一樣,一層一層的連到最頂部store。所以在沒有找到時,Vuex會給你報個錯誤。
// 聲明了Vuex但沒有找到store時的狀況 if (vuex) { if (!this.$store) { console.warn( "[vuex] store not injected. make sure to " + "provide the store option in your root component." ) }對Vuex聲明的內(nèi)容,進(jìn)行改造
接下來,則是對Vuex聲明的內(nèi)容,進(jìn)行改造。
首先的是獲取Vuex對象的內(nèi)容:
let { state, getters, actions } = vuex
同時,在這兒還看到了對過時API的處理。感覺算是意料之外的驚喜。
// handle deprecated state option // 如果使用state而不是getters來獲取Store的數(shù)據(jù),則會提示你state已經(jīng)過時的,你需要使用新的api。 // 但是,這兒也做了兼容,確保升級時服務(wù)不會掛掉。 if (state && !getters) { console.warn( "[vuex] vuex.state option will been deprecated in 1.0. " + "Use vuex.getters instead." ) getters = state }
接下來,則是對getters和actions的處理:
// getters if (getters) { options.computed = options.computed || {} for (let key in getters) { defineVuexGetter(this, key, getters[key]) } } // actions if (actions) { options.methods = options.methods || {} for (let key in actions) { options.methods[key] = makeBoundAction(this.$store, actions[key], key) } }
可以看出,在這兒對getters和actions都進(jìn)行了額外處理。
在這兒,我們講述actions的額外處理,至于getters,涉及了過多的Vue,而我不是很熟悉。等我多鉆研后,再寫吧。
對整個Actions的改造,首先是Vuex的檢測:
// actions if (actions) { // options.methods是Vue的methods選項 options.methods = options.methods || {} for (let key in actions) { options.methods[key] = makeBoundAction(this.$store, actions[key], key) } }
在這兒,我們一點(diǎn)一點(diǎn)的剖析??梢钥闯觯械腶ctions,都會被makeBoundAction函數(shù)處理,并加入Vue的methods選項中。
那么看來,makeBoundAction函數(shù)就是我要找的答案了。
接下來貼出makeBoundAction函數(shù)的源代碼:
/** * Make a bound-to-store version of a raw action function. * * @param {Store} store * @param {Function} action * @param {String} key */ function makeBoundAction(store, action, key) { if (typeof action !== "function") { console.warn(`[vuex] Action bound to key "vuex.actions.${key}" is not a function.`) } return function vuexBoundAction(...args) { return action.call(this, store, ...args) } }
事情到這兒,其實已經(jīng)豁然明朗了。
我在Vuex中傳入的actions,實際會被處理為vuexBoundAction,并加入options.methods中。
在調(diào)用這個函數(shù)時,實際上的action會使用call,來改變this指向并傳入store作為第一個參數(shù)。而store是有dispatch這個函數(shù)的。
那么,在我傳入{dispatch}時,自然而然就會解構(gòu)賦值。
這樣的話,也形成了閉包,確保action能訪問到store。
今天應(yīng)該算是解決了心中的一個大疑惑,還是那句話:
沒有無緣無故的愛,也沒有無緣無故的恨,更沒有無緣無故冒出來的代碼。
整個源代碼讀下來一遍,雖然有些部分不太理解,但是對ES6和一些代碼的使用的理解又加深了一步。比如這回就鞏固了我關(guān)于ES6解構(gòu)賦值的知識。而且還收獲了很多別的東西??偠灾斋@頗豐~
最后的,依然是那句話:前端路漫漫,且行且歌。
最后附上本人博客地址和原文鏈接,希望能與各位多多交流。
Lxxyx的前端樂園
原文鏈接:Vuex源碼閱讀筆記
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/87743.html
摘要:為了防止某些文檔或腳本加載別的域下的未知內(nèi)容,防止造成泄露隱私,破壞系統(tǒng)等行為發(fā)生。模式構(gòu)建函數(shù)響應(yīng)式前端架構(gòu)過程中學(xué)到的經(jīng)驗?zāi)J降牟煌幵谟?,它主要專注于恰?dāng)?shù)貙崿F(xiàn)應(yīng)用程序狀態(tài)突變。嚴(yán)重情況下,會造成惡意的流量劫持等問題。 今天是編輯周刊的日子。所以文章很多和周刊一樣。微信不能發(fā)鏈接,點(diǎn)了也木有用,所以請記得閱讀原文~ 發(fā)個動圖娛樂下: 使用 SVG 動畫制作游戲 使用 GASP ...
摘要:鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫了一篇下的使用方法,傳送門使用構(gòu)建單頁應(yīng)用新篇華麗的分割線原文地址前言在最近學(xué)習(xí)的時候,看到國外一篇講述了如何使用和來構(gòu)建一個簡單筆記的單頁應(yīng)用的文章。 鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫了一篇 vue2.0 下的 vuex 使用方法,傳送門:使用 Vuex + Vue.js 構(gòu)建單頁應(yīng)用【新篇】 ---------...
摘要:鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫了一篇下的使用方法,傳送門使用構(gòu)建單頁應(yīng)用新篇華麗的分割線原文地址前言在最近學(xué)習(xí)的時候,看到國外一篇講述了如何使用和來構(gòu)建一個簡單筆記的單頁應(yīng)用的文章。 鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫了一篇 vue2.0 下的 vuex 使用方法,傳送門:使用 Vuex + Vue.js 構(gòu)建單頁應(yīng)用【新篇】 ---------...
摘要:鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫了一篇下的使用方法,傳送門使用構(gòu)建單頁應(yīng)用新篇華麗的分割線原文地址前言在最近學(xué)習(xí)的時候,看到國外一篇講述了如何使用和來構(gòu)建一個簡單筆記的單頁應(yīng)用的文章。 鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫了一篇 vue2.0 下的 vuex 使用方法,傳送門:使用 Vuex + Vue.js 構(gòu)建單頁應(yīng)用【新篇】 ---------...
摘要:鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫了一篇下的使用方法,傳送門使用構(gòu)建單頁應(yīng)用新篇華麗的分割線原文地址前言在最近學(xué)習(xí)的時候,看到國外一篇講述了如何使用和來構(gòu)建一個簡單筆記的單頁應(yīng)用的文章。 鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫了一篇 vue2.0 下的 vuex 使用方法,傳送門:使用 Vuex + Vue.js 構(gòu)建單頁應(yīng)用【新篇】 ---------...
閱讀 952·2021-09-27 13:36
閱讀 908·2021-09-08 09:35
閱讀 1078·2021-08-12 13:25
閱讀 1450·2019-08-29 16:52
閱讀 2920·2019-08-29 15:12
閱讀 2740·2019-08-29 14:17
閱讀 2627·2019-08-26 13:57
閱讀 1023·2019-08-26 13:51