欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺談Vuex注入Vue生命周期的過程

 更新時(shí)間:2019年05月20日 10:49:28   作者:小生方勤  
這篇文章主要介紹了Vuex 注入 Vue 生命周期的過程,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

這篇文章是【前端詞典】系列文章的第 13 篇文章,接下的 9 篇我會圍繞著 Vue 展開,希望這 9 篇文章可以使大家加深對 Vue 的了解。當(dāng)然這些文章的前提是默認(rèn)你對 Vue 有一定的基礎(chǔ)。如果一點(diǎn)基礎(chǔ)都沒有,建議先看官方文檔。

第一篇文章我會結(jié)合 Vue 和 Vuex 的部分源碼,來說明 Vuex 注入 Vue 生命周期的過程。

說到源碼,其實(shí)沒有想象的那么難。也和我們平時(shí)寫業(yè)務(wù)代碼差不多,都是方法的調(diào)用。但是源碼的調(diào)用樹會復(fù)雜很多。

為何使用 Vuex

使用 Vue 我們就不可避免的會遇到組件間共享的數(shù)據(jù)或狀態(tài)。應(yīng)用的業(yè)務(wù)代碼逐漸復(fù)雜,props、事件、事件總線等通信的方式的弊端就會愈發(fā)明顯。這個(gè)時(shí)候我們就需要 Vuex 。Vuex 是一個(gè)專門為 Vue 設(shè)計(jì)的狀態(tài)管理工具。

狀態(tài)管理是 Vue 組件解耦的重要手段。

它借鑒了 Flux、redux 的基本思想,將狀態(tài)抽離到全局,形成一個(gè) Store。

 Vuex 不限制你的代碼結(jié)構(gòu),但需要遵守一些規(guī)則:

  • 應(yīng)用層級的狀態(tài)應(yīng)該集中到單個(gè) store 對象中
  • 提交 mutation 是更改狀態(tài)的唯一方法,并且這個(gè)過程是同步的
  • 異步邏輯都應(yīng)該封裝到 action 里面

 Vuex 注入 Vue 生命周期的過程

我們在安裝插件的時(shí)候,總會像下面一樣用 Vue.use() 來載入插件,可是 Vue.use() 做了什么呢?

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

Vue.use() 做了什么

安裝 Vue.js 插件。如果插件是一個(gè)對象,必須提供 install 方法。如果插件是一個(gè)函數(shù),它會被作為 install 方法。install 方法調(diào)用時(shí),會將 Vue 作為參數(shù)傳入。

以上是官方文檔的解釋。

接下來我們從源碼部分來看看 Vue.use() 都做了什么。

Vue 源碼在 initGlobalAPI 入口方法中調(diào)用了 initUse (Vue) 方法,這個(gè)方法定義了 Vue.use() 需要做的內(nèi)容。

function initGlobalAPI (Vue) {
 ......
 initUse(Vue);
 initMixin$1(Vue); // 下面講 Vue.mixin 會提到
 ......
}

function initUse (Vue) {
 Vue.use = function (plugin) {
 var installedPlugins = (this._installedPlugins || (this._installedPlugins = []));
 /* 判斷過這個(gè)插件是否已經(jīng)安裝 */
 if (installedPlugins.indexOf(plugin) > -1) {
 return this
 }
 var args = toArray(arguments, 1);
 args.unshift(this);
 /* 判斷插件是否有 install 方法 */
 if (typeof plugin.install === 'function') {
 plugin.install.apply(plugin, args);
 } else if (typeof plugin === 'function') {
 plugin.apply(null, args);
 }
 installedPlugins.push(plugin);
 return this
 };
}

這段代碼主要做了兩件事情:

  1. 一件是防止重復(fù)安裝相同的 plugin
  2. 另一件是初始化 plugin

插件的 install 方法

看完以上源碼,我們知道插件(Vuex)需要提供一個(gè) install 方法。那么我們看看 Vuex 源碼中是否有這個(gè)方法。結(jié)果當(dāng)然是有的:

/* 暴露給外部的 install 方法 */
function install (_Vue) {
 /* 避免重復(fù)安裝(Vue.use 內(nèi)部也會檢測一次是否重復(fù)安裝同一個(gè)插件)*/
 if (Vue && _Vue === Vue) {
 {
 console.error(
 '[vuex] already installed. Vue.use(Vuex) should be called only once.'
 );
 }
 return
 }
 Vue = _Vue;
 /* 將 vuexInit 混淆進(jìn) Vue 的 beforeCreate(Vue2.0) 或 _init 方法(Vue1.0) */
 applyMixin(Vue);
}

這段代碼主要做了兩件事情:

  1. 一件是防止 Vuex 被重復(fù)安裝
  2. 另一件是執(zhí)行 applyMixin ,目的是執(zhí)行 vuexInit 方法初始化 Vuex

接下來 我們看看 applyMixin(Vue) 源碼:

/* 將 vuexInit 混淆進(jìn) Vue 的 beforeCreate */
function applyMixin (Vue) {
 var version = Number(Vue.version.split('.')[0]);
 if (version >= 2) {
 Vue.mixin({ beforeCreate: vuexInit });
 } else {
 /* Vue1.0 的處理邏輯,此處省略 */
 ......
 }
 function vuexInit () {
 ......
 }
}

從上面的源碼,可以看出 Vue.mixin 方法將 vuexInit 方法混淆進(jìn) beforeCreate 鉤子中,也是因?yàn)檫@個(gè)操作,所以每一個(gè) vm 實(shí)例都會調(diào)用 vuexInit 方法。那么 vuexInit 又做了什么呢?

vuexInit()

我們在使用 Vuex 的時(shí)候,需要將 store 傳入到 Vue 實(shí)例中去。

new Vue({
 el: '#app',
 store
});

但是我們卻在每一個(gè) vm 中都可以訪問該 store,這個(gè)就需要靠 vuexInit 了。

 function vuexInit () {
 const options = this.$options
 if (options.store) {
 /* 根節(jié)點(diǎn)存在 stroe 時(shí) */
 this.$store = typeof options.store === 'function'
 ? options.store()
 : options.store
 } else if (options.parent && options.parent.$store) {
 /* 子組件直接從父組件中獲取 $store,這樣就保證了所有組件都公用了全局的同一份 store*/
 this.$store = options.parent.$store
 }
 }

根節(jié)點(diǎn)存在 stroe 時(shí),則直接將 options.store 賦值給 this.$store 。否則則說明不是根節(jié)點(diǎn),從父節(jié)點(diǎn)的 $store 中獲取。

通過這步的操作,我們就以在任意一個(gè) vm 中通過 this.$store 來訪問 Store 的實(shí)例。接下來我們反過來說說 Vue.mixin()。

Vue.mixin()

全局注冊一個(gè)混入,影響注冊之后所有創(chuàng)建的每個(gè) Vue 實(shí)例。插件作者可以使用混入,向組件注入自定義的行為。 不推薦在應(yīng)用代碼中使用。

在 vue 的 initGlobalAPI 入口方法中調(diào)用了 initMixin$1(Vue) 方法:

function initMixin$1 (Vue) {
 Vue.mixin = function (mixin) {
 this.options = mergeOptions(this.options, mixin);
 return this
 };
}

Vuex 注入 Vue 生命周期的過程大概就是這樣,如果你感興趣的話,你可以直接看看 Vuex 的源碼,接下來我們說說 Store。

Store

上面我們講到了 vuexInit 會從 options 中獲取 Store。所以接下來會講到 Store 是怎么來的呢?

我們使用 Vuex 的時(shí)候都會定義一個(gè)和下面類似的 Store 實(shí)例。

import Vue from 'vue'
import Vuex from 'vuex'
import mutations from './mutations'

Vue.use(Vuex)

const state = {
 showState: 0,    
}

export default new Vuex.Store({
 strict: true,
	state,
	getters,
})

不要在發(fā)布環(huán)境下啟用嚴(yán)格模式。嚴(yán)格模式會深度監(jiān)測狀態(tài)樹來檢測不合規(guī)的狀態(tài)變更 —— 請確保在發(fā)布環(huán)境下關(guān)閉嚴(yán)格模式,以避免性能損失。

state 的響應(yīng)式

你是否關(guān)心 state 是如何能夠響應(yīng)式呢?這個(gè)主要是通過 Store 的構(gòu)造函數(shù)中調(diào)用的 resetStoreVM(this, state) 方法來實(shí)現(xiàn)的。

這個(gè)方法主要是重置一個(gè)私有的 _vm(一個(gè) Vue 的實(shí)例) 對象。這個(gè) _vm 對象會保留我們的 state 樹,以及用計(jì)算屬性的方式存儲了 store 的 getters?,F(xiàn)在具體看看它的實(shí)現(xiàn)過程。

/* 使用 Vue 內(nèi)部的響應(yīng)式注冊 state */
function resetStoreVM (store, state, hot) {
 /* 存放之前的vm對象 */
 const oldVm = store._vm 

 store.getters = {}
 const wrappedGetters = store._wrappedGetters
 const computed = {}

 /* 通過 Object.defineProperty 方法為 store.getters 定義了 get 方法。當(dāng)在組件中調(diào)用 this.$store.getters.xxx 這個(gè)方法的時(shí)候,會訪問 store._vm[xxx]*/
 forEachValue(wrappedGetters, (fn, key) => {
 computed[key] = partial(fn, store)
 Object.defineProperty(store.getters, key, {
 get: () => store._vm[key],
 enumerable: true // for local getters
 })
 })

 const silent = Vue.config.silent
 /* 設(shè)置 silent 為 true 的目的是為了取消 _vm 的所有日志和警告 */
 Vue.config.silent = true
 /* 這里new了一個(gè)Vue對象,運(yùn)用Vue內(nèi)部的響應(yīng)式實(shí)現(xiàn)注冊state以及computed*/
 store._vm = new Vue({
 data: {
 $$state: state
 },
 computed
 })
 Vue.config.silent = silent

 /* 使能嚴(yán)格模式,Vuex 中對 state 的修改只能在 mutation 的回調(diào)函數(shù)里 */
 if (store.strict) {
 enableStrictMode(store)
 }

 if (oldVm) {
 /* 解除舊 vm 的 state 的引用,并銷毀這個(gè)舊的 _vm 對象 */
 if (hot) {
 store._withCommit(() => {
 oldVm._data.$$state = null
 })
 }
 Vue.nextTick(() => oldVm.$destroy())
 }
}

state 的響應(yīng)式大概就是這樣實(shí)現(xiàn)的,也就是初始化 resetStoreVM 方法的過程。

看看 Store 的 commit 方法

我們知道 commit 方法是用來觸發(fā) mutation 的。

commit (_type, _payload, _options) {
 /* unifyObjectStyle 方法校參 */
 const {
 type,
 payload,
 options
 } = unifyObjectStyle(_type, _payload, _options)

 const mutation = { type, payload }
 /* 找到相應(yīng)的 mutation 方法 */
 const entry = this._mutations[type]
 if (!entry) {
 if (process.env.NODE_ENV !== 'production') {
 console.error(`[vuex] unknown mutation type: ${type}`)
 }
 return
 }
 /* 執(zhí)行 mutation 中的方法 */
 this._withCommit(() => {
 entry.forEach(function commitIterator (handler) {
 handler(payload)
 })
 })
 /* 通知所有訂閱者,傳入當(dāng)前的 mutation 對象和當(dāng)前的 state */
 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'
 )
 }
}

該方法先進(jìn)行參數(shù)風(fēng)格校驗(yàn),然后利用 _withCommit 方法執(zhí)行本次批量觸發(fā) mutation 處理函數(shù)。執(zhí)行完成后,通知所有 _subscribers (訂閱函數(shù))本次操作的 mutation 對象以及當(dāng)前的 state 狀態(tài)。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Vue 根據(jù)條件判斷van-tab的顯示方式

    Vue 根據(jù)條件判斷van-tab的顯示方式

    這篇文章主要介紹了Vue 根據(jù)條件判斷van-tab的顯示方式,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • vue-admin-template解決登錄和跨域問題解決

    vue-admin-template解決登錄和跨域問題解決

    本文主要介紹了vue-admin-template解決登錄和跨域問題解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • 使用vue-cli搭建SPA項(xiàng)目的詳細(xì)過程

    使用vue-cli搭建SPA項(xiàng)目的詳細(xì)過程

    vue-cli是vue.js的腳手架,用于自動生成vue.js+webpack的項(xiàng)目模板,本文通過實(shí)例代碼給大家介紹vue-cli搭建SPA項(xiàng)目的詳細(xì)過程,感興趣的朋友跟隨小編一起看看吧
    2022-09-09
  • vue中的加密方式總結(jié)

    vue中的加密方式總結(jié)

    這篇文章主要為大家詳細(xì)介紹了vue中常見的加密方式實(shí)現(xiàn),例如js-base64、crypto-js、jsencrypt、bcryptjs,文中的示例代碼講解詳細(xì),需要的小伙伴可以參考一下
    2023-11-11
  • Vue2?this?能夠直接獲取到?data?和?methods?的原理分析

    Vue2?this?能夠直接獲取到?data?和?methods?的原理分析

    這篇文章主要介紹了Vue2?this能夠直接獲取到data和methods的原理分析,因?yàn)閙ethods里的方法通過bind指定了this為new?Vue的實(shí)例
    2022-06-06
  • 詳解Vue如何實(shí)現(xiàn)字母驗(yàn)證碼

    詳解Vue如何實(shí)現(xiàn)字母驗(yàn)證碼

    這篇文章主要為大家介紹了Vue如何實(shí)現(xiàn)字母驗(yàn)證碼詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • 淺入深出Vue之自動化路由

    淺入深出Vue之自動化路由

    這篇文章主要介紹了淺入深出Vue之自動化路由,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Vue3中emits與attrs的區(qū)別分析

    Vue3中emits與attrs的區(qū)別分析

    這篇文章主要給大家介紹了關(guān)于Vue3中emits與attrs區(qū)別的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用vue具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2021-10-10
  • Element-plus封裝搜索組件的實(shí)現(xiàn)

    Element-plus封裝搜索組件的實(shí)現(xiàn)

    在后臺管理系統(tǒng)中,經(jīng)常需要在多個(gè)頁面中使用搜索功能,本文就來介紹一下Element-plus封裝搜索組件的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-08-08
  • vue+echarts實(shí)現(xiàn)動態(tài)繪制圖表及異步加載數(shù)據(jù)的方法

    vue+echarts實(shí)現(xiàn)動態(tài)繪制圖表及異步加載數(shù)據(jù)的方法

    vue寫的后臺管理,需要將表格數(shù)據(jù)繪制成圖表(折線圖,柱狀圖),圖表數(shù)據(jù)都是通過接口請求回來的。這篇文章主要介紹了vue+echarts 動態(tài)繪制圖表及異步加載數(shù)據(jù)的相關(guān)知識,需要的朋友可以參考下
    2018-10-10

最新評論