国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Vuex源碼閱讀筆記

hosition / 1357人閱讀

摘要:而鉆研最好的方式,就是閱讀的源代碼。整個(gè)的源代碼,核心內(nèi)容包括兩部分。逃而動(dòng)手腳的代碼,就存在于源代碼的中。整個(gè)源代碼讀下來(lái)一遍,雖然有些部分不太理解,但是對(duì)和一些代碼的使用的理解又加深了一步。

筆記中的Vue與Vuex版本為1.0.21和0.6.2,需要閱讀者有使用Vue,Vuex,ES6的經(jīng)驗(yàn)。

起因

俗話說(shuō)得好,沒(méi)有無(wú)緣無(wú)故的愛(ài),也沒(méi)有無(wú)緣無(wú)故的恨,更不會(huì)無(wú)緣無(wú)故的去閱讀別人的源代碼。
之所以會(huì)去閱讀Vuex的源代碼,是因?yàn)樵趧傞_(kāi)始接觸Vuex時(shí),就在官方文檔的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還好說(shuō),能看懂,但是下面使用ES6寫(xiě)法的Action是什么鬼呀喂(摔!)
雖然知道有解構(gòu)賦值,但是那個(gè){ dispatch }又是從哪兒冒出來(lái)的呀喂!明明我在調(diào)用時(shí),沒(méi)有傳這個(gè)參數(shù)呀!
之前因?yàn)橼s項(xiàng)目進(jìn)度,所以抱著能用就行的態(tài)度,也就沒(méi)管那么多。如今有了空閑時(shí)間,必須好好鉆研一下呀。
而鉆研最好的方式,就是閱讀Vuex的源代碼。這樣就能弄清楚,那個(gè){ dispatch }到底從哪兒冒出來(lái)的。

Vuex源代碼簡(jiǎn)介

Vuex的源代碼量挺少的,加起來(lái)也才600行不到,但是其中大量使用了ES6的語(yǔ)法,且部分功能(如Vuex初始化)使用到了Vue。所以讀起來(lái)還是有些費(fèi)勁的。
整個(gè)Vuex的源代碼,核心內(nèi)容包括兩部分。一部分是Store的構(gòu)造函數(shù),另一部分則是Vuex的初始化函數(shù)。
而剛才問(wèn)題的答案,就在第二部分。

問(wèn)題場(chǎng)景還原

首先要介紹的,就是Vuex在Vue項(xiàng)目中的初始化。這兒貼一段代碼:
首先是Vuex中,我寫(xiě)的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)
  })
}

這個(gè)則是頂層組件,調(diào)用store的地方。由于Vuex的特點(diǎn),store只需要在最頂層的組件聲明一次。



接下來(lái)則是組件中,則是實(shí)際調(diào)用Vuex的代碼。

// index.vue
import { getMe } from "./../global/Vuex/action"

export default {

  vuex: {
    actions: {
      getMe
    },
    getters: {
      // 從state中獲取信息
      user: state => state.user
    }
  },

  ready() {
    // 開(kāi)始獲取用戶信息
    this.getMe()
  }
}

在這兒,可以很明顯的看出,我在使用this.getMe()時(shí),是沒(méi)有任何參數(shù)的。但是在getMe函數(shù)的定義中,是需要解構(gòu)賦值出{dispatch}的。
就好比說(shuō)這個(gè):

function getX({ x }) {
  console.log(x)
}

getX({ x: 3, y: 5 })
// 3

你得傳入相應(yīng)的參數(shù),才能進(jìn)行解構(gòu)賦值。
同時(shí),我注意到在Vuex的Actions調(diào)用,需要在Vue的options的Vuex.actions中先聲明,之后才能使用。
那么,一定是Vuex對(duì)這個(gè)Action動(dòng)了手腳。(逃)
而動(dòng)手腳的代碼,就存在于Vuex源代碼的override.js中。這個(gè)文件,是用于初始化Vuex的。

Vuex的初始化

override.js中,有個(gè)vuexInit的函數(shù)。看名字就知道,這是拿來(lái)初始化Vuex的。
在代碼開(kāi)頭,有這么一句:

const options = this.$options
const { store, vuex } = options
// 感覺(jué)解構(gòu)賦值真的很棒,這樣寫(xiě)能省很多時(shí)間。
// 下面的是老寫(xiě)法
// const store = options.store
// const vuex = options.vuex

在這兒,用于是在Vue中調(diào)用,所以this指向Vue,而this.$options則是Vue的配置項(xiàng)。
也就是寫(xiě)Vue組件時(shí)的:
export default {……一些配置}
這里,就把Vue配置項(xiàng)的store和vuex抽離出來(lái)了。

搜尋store

接下來(lái),則看到了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就會(huì)是undefined。但是我們需要找store。
于是Vuex提供了向父級(jí)(Vue中的功能)尋找store的功能。不難看出,這兒父級(jí)的$store如果不存在,那么其實(shí)他也會(huì)到自己的父級(jí)去尋找。直到找到為止。
就想一條鎖鏈一樣,一層一層的連到最頂部store。所以在沒(méi)有找到時(shí),Vuex會(huì)給你報(bào)個(gè)錯(cuò)誤。

// 聲明了Vuex但沒(méi)有找到store時(shí)的狀況
if (vuex) {
  if (!this.$store) {
    console.warn(
      "[vuex] store not injected. make sure to " +
      "provide the store option in your root component."
    )
  }
對(duì)Vuex聲明的內(nèi)容,進(jìn)行改造

接下來(lái),則是對(duì)Vuex聲明的內(nèi)容,進(jìn)行改造。
首先的是獲取Vuex對(duì)象的內(nèi)容:

let { state, getters, actions } = vuex

同時(shí),在這兒還看到了對(duì)過(guò)時(shí)API的處理。感覺(jué)算是意料之外的驚喜。

// handle deprecated state option
// 如果使用state而不是getters來(lái)獲取Store的數(shù)據(jù),則會(huì)提示你state已經(jīng)過(guò)時(shí)的,你需要使用新的api。
// 但是,這兒也做了兼容,確保升級(jí)時(shí)服務(wù)不會(huì)掛掉。
if (state && !getters) {
  console.warn(
    "[vuex] vuex.state option will been deprecated in 1.0. " +
    "Use vuex.getters instead."
  )
  getters = state
}

接下來(lái),則是對(duì)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)
  }
}

可以看出,在這兒對(duì)getters和actions都進(jìn)行了額外處理。
在這兒,我們講述actions的額外處理,至于getters,涉及了過(guò)多的Vue,而我不是很熟悉。等我多鉆研后,再寫(xiě)吧。

Actions的改造

對(duì)整個(gè)Actions的改造,首先是Vuex的檢測(cè):

// actions
if (actions) {
  // options.methods是Vue的methods選項(xiàng)
  options.methods = options.methods || {}
  for (let key in actions) {
    options.methods[key] = makeBoundAction(this.$store, actions[key], key)
  }
}

在這兒,我們一點(diǎn)一點(diǎn)的剖析。可以看出,所有的actions,都會(huì)被makeBoundAction函數(shù)處理,并加入Vue的methods選項(xiàng)中。
那么看來(lái),makeBoundAction函數(shù)就是我要找的答案了。
接下來(lái)貼出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)
  }
}

事情到這兒,其實(shí)已經(jīng)豁然明朗了。
我在Vuex中傳入的actions,實(shí)際會(huì)被處理為vuexBoundAction,并加入options.methods中。
在調(diào)用這個(gè)函數(shù)時(shí),實(shí)際上的action會(huì)使用call,來(lái)改變this指向并傳入store作為第一個(gè)參數(shù)。而store是有dispatch這個(gè)函數(shù)的。
那么,在我傳入{dispatch}時(shí),自然而然就會(huì)解構(gòu)賦值。
這樣的話,也形成了閉包,確保action能訪問(wèn)到store。

結(jié)語(yǔ)

今天應(yīng)該算是解決了心中的一個(gè)大疑惑,還是那句話:

沒(méi)有無(wú)緣無(wú)故的愛(ài),也沒(méi)有無(wú)緣無(wú)故的恨,更沒(méi)有無(wú)緣無(wú)故冒出來(lái)的代碼。

整個(gè)源代碼讀下來(lái)一遍,雖然有些部分不太理解,但是對(duì)ES6和一些代碼的使用的理解又加深了一步。比如這回就鞏固了我關(guān)于ES6解構(gòu)賦值的知識(shí)。而且還收獲了很多別的東西。總而言之,收獲頗豐~
最后的,依然是那句話:前端路漫漫,且行且歌。

最后附上本人博客地址和原文鏈接,希望能與各位多多交流。

Lxxyx的前端樂(lè)園
原文鏈接:Vuex源碼閱讀筆記

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/87743.html

相關(guān)文章

  • 前端閱讀筆記 2016-11-25

    摘要:為了防止某些文檔或腳本加載別的域下的未知內(nèi)容,防止造成泄露隱私,破壞系統(tǒng)等行為發(fā)生。模式構(gòu)建函數(shù)響應(yīng)式前端架構(gòu)過(guò)程中學(xué)到的經(jīng)驗(yàn)?zāi)J降牟煌幵谟冢饕獙W⒂谇‘?dāng)?shù)貙?shí)現(xiàn)應(yīng)用程序狀態(tài)突變。嚴(yán)重情況下,會(huì)造成惡意的流量劫持等問(wèn)題。 今天是編輯周刊的日子。所以文章很多和周刊一樣。微信不能發(fā)鏈接,點(diǎn)了也木有用,所以請(qǐng)記得閱讀原文~ 發(fā)個(gè)動(dòng)圖娛樂(lè)下: 使用 SVG 動(dòng)畫(huà)制作游戲 使用 GASP ...

    KoreyLee 評(píng)論0 收藏0
  • 使用 Vuex + Vue.js 構(gòu)建單頁(yè)應(yīng)用

    摘要:鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫(xiě)了一篇下的使用方法,傳送門(mén)使用構(gòu)建單頁(yè)應(yīng)用新篇華麗的分割線原文地址前言在最近學(xué)習(xí)的時(shí)候,看到國(guó)外一篇講述了如何使用和來(lái)構(gòu)建一個(gè)簡(jiǎn)單筆記的單頁(yè)應(yīng)用的文章。 鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫(xiě)了一篇 vue2.0 下的 vuex 使用方法,傳送門(mén):使用 Vuex + Vue.js 構(gòu)建單頁(yè)應(yīng)用【新篇】 ---------...

    tomorrowwu 評(píng)論0 收藏0
  • 使用 Vuex + Vue.js 構(gòu)建單頁(yè)應(yīng)用

    摘要:鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫(xiě)了一篇下的使用方法,傳送門(mén)使用構(gòu)建單頁(yè)應(yīng)用新篇華麗的分割線原文地址前言在最近學(xué)習(xí)的時(shí)候,看到國(guó)外一篇講述了如何使用和來(lái)構(gòu)建一個(gè)簡(jiǎn)單筆記的單頁(yè)應(yīng)用的文章。 鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫(xiě)了一篇 vue2.0 下的 vuex 使用方法,傳送門(mén):使用 Vuex + Vue.js 構(gòu)建單頁(yè)應(yīng)用【新篇】 ---------...

    cnsworder 評(píng)論0 收藏0
  • 使用 Vuex + Vue.js 構(gòu)建單頁(yè)應(yīng)用

    摘要:鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫(xiě)了一篇下的使用方法,傳送門(mén)使用構(gòu)建單頁(yè)應(yīng)用新篇華麗的分割線原文地址前言在最近學(xué)習(xí)的時(shí)候,看到國(guó)外一篇講述了如何使用和來(lái)構(gòu)建一個(gè)簡(jiǎn)單筆記的單頁(yè)應(yīng)用的文章。 鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫(xiě)了一篇 vue2.0 下的 vuex 使用方法,傳送門(mén):使用 Vuex + Vue.js 構(gòu)建單頁(yè)應(yīng)用【新篇】 ---------...

    levius 評(píng)論0 收藏0
  • 使用 Vuex + Vue.js 構(gòu)建單頁(yè)應(yīng)用

    摘要:鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫(xiě)了一篇下的使用方法,傳送門(mén)使用構(gòu)建單頁(yè)應(yīng)用新篇華麗的分割線原文地址前言在最近學(xué)習(xí)的時(shí)候,看到國(guó)外一篇講述了如何使用和來(lái)構(gòu)建一個(gè)簡(jiǎn)單筆記的單頁(yè)應(yīng)用的文章。 鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫(xiě)了一篇 vue2.0 下的 vuex 使用方法,傳送門(mén):使用 Vuex + Vue.js 構(gòu)建單頁(yè)應(yīng)用【新篇】 ---------...

    UsherChen 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<