碰見面試 Vuex原理解析

碰見面試 Vuex原理解析

1、前言

自從學習了VUE框架,其中必不可少的會用到vuex這個核心插件,並且在作項目的時候,基本都會使用,可能你會使用vuex狀態管理,可是對vuex原理存在着或多或少的的疑惑或不解,這篇文章就針對vuex原理進行研究,但願能幫助到你們,若是有不許確的地方,你們多多指教。。。html

2、Vuex是什麼?

Vuex是專門爲Vue服務,用於管理頁面的數據狀態、提供統一數據操做的生態系統,至關於數據庫mongoDB,MySQL等,任何組件均可以存取倉庫中的數據。其中vuex相似的 仍是有Redux,Redux大多用於React,針對Redux後續在作補充,如今就讓咱們好好了解下Vuex究竟是個啥東西?前端

概念理解性(必讀

Vuex採用MVC模式中的Model層,規定全部的數據必須經過action--->mutaion--->state這個流程進行來改變狀態的。再結合Vue的數據視圖雙向綁定實現頁面的更新。統一頁面狀態管理,可讓複雜的組件交互變的簡單清晰,同時在調試時也能夠經過DEVtools去查看狀態。vue

在當前前端的spa模塊化項目中不可避免的是某些變量須要在全局範圍內引用,此時父子組件的傳值,子父組件間的傳值,兄弟組件間的傳值成了咱們須要解決的問題。雖然vue中提供了props(父傳子)commit(子傳父)兄弟間也能夠用localstorage和sessionstorage。可是這種方式在項目開發中帶來的問題比他解決的問題(難管理,難維護,代碼複雜,安全性低)更多。vuex的誕生也是爲了解決這些問題,從而大大提升咱們vue項目的開發效率。git

拋出問題

使用Vuex只需執行 Vue.use(Vuex),並在Vue的配置中傳入一個store對象的示例,store是如何實現注入的?
state內部是如何實現支持模塊配置和模塊嵌套的?
在執行dispatch觸發action(commit同理)的時候,只需傳入(type, payload),action執行函數中第一個參數store從哪裏獲取的?
如何區分state是外部直接修改,仍是經過mutation方法修改的?
複製代碼

3、vue和vuex關係

看一下這個vue響應式的例子,vue中的data 、methods、computed,能夠實現響應式。github

視圖經過點擊事件,觸發methods中的increment方法,能夠更改state中count的值,一旦count值發生變化,computed中的函數可以把getCount更新到視圖。web

<div id="app">
        <button @click="increment"></button>
        {{getcount}}
    </app>
    new Vue({
        el: "#app",
        // state
        data () {
         return {
            count: 0
         }
        },
         // view
        computed: {
            getCount(){
                return this.count
            }
        },
        // actions
        methods: {
         increment () {
            this.count++
         }
        },
    })
複製代碼

那麼vuex又和vue這個響應式的例子有什麼關係呢?面試

咱們能夠用vuex實現和vue一樣的響應式功能。
複製代碼

其實他們原理時同樣的,vuex中也有四個屬性值:state、getters、mutations、actions。。vuex

在沒有actions的狀況下:數據庫

  • 數據:state --> data
  • 獲取數據:getters --> computed
  • 更改數據:mutations --> methods

視圖經過點擊事件,觸發mutations中方法,能夠更改state中的數據,一旦state數據發生更改,getters把數據反映到視圖。json

那麼actions,能夠理解處理異步,而單純多加的一層。

既然提到了mutions actions這時候 就不得不提commit,dispatch這兩個有什麼做用呢?

在vue例子中,經過click事件,觸發methods中的方法。當存在異步時,而在vuex中須要dispatch來觸發actions中的方法,actions中的commit能夠觸發mutations中的方法。同步,則直接在組件中commit觸發vuex中mutations中的方法。

4、vuex實現

下面咱們看下vuex中能像vue中實現改變狀態,更新視圖的功能:

Vuex.js

const store =  new Vuex.Store({
    
    state: {
        count: 0
    },
    
    //state的值只能經過mutations來修改
    mutations: {
        increment(state) {
            state.count++
        }
    },
    
   //this.$store.commit("increment")觸發mutations中函數"increment"
    actions: {
        increment({commit}) {
             commit("increment"); //this.$store.commit("increment")
        }
     
    },
    
   //經過getter中的方法來獲取state值
    getters: {
        getCount(state) {
            return state.count
        }
    }
    })
     
    export default store

複製代碼

App.vue

<template>
    <div id="app">
            <button @click="increment">增長</button>
            <!-- 有時候不能直接 強制使用store裏面的狀態 this.$store.state.count -->
            {{this.$store.getters.getCount}}
    </div>
    </template>
     
    <script>
    export default {
        methods: {
        increment(){
                //this.$store.dispatch("increment")觸發actions函數"increment"
                this.$store.dispatch("increment")
            }
        }
    }
    </script>

複製代碼

5、源碼分析:

如今咱們已經瞭解vuex能實現和像vue雙向數據綁定--更新試圖的功能,下面咱們重點說說vuex源碼的實現:

5.一、store注入組件install方法

解答問題:vuex的store是如何注入到組件中的?

首先使用vuex,須要安裝插件:

Vue.use(Vuex); // vue的插件機制,安裝vuex插件

複製代碼

當ues(Vuex)時候,會調用vuex中的install方法,裝在vuex! 下面時install的核心源碼:

Vue.mixin({
        beforeCreate() {
            if (this.$options && this.$options.store) {
                //找到根組件 main 上面掛一個$store
                this.$store = this.$options.store
                // console.log(this.$store);

            } else {
                //非根組件指向其父組件的$store
                this.$store = this.$parent && this.$parent.$store
            }
        }
    })
複製代碼

可見,store注入 vue的實例組件的方式,是經過vue的 mixin機制,藉助vue組件的生命週期 鉤子 beforeCreate 完成的。即 每一個vue組件實例化過程當中,會在 beforeCreate 鉤子前調用 vuexInit 方法。

解答問題:vuex的state和getters是如何映射到各個組件實例中響應式更新狀態呢?

5.二、new vue實現雙向數據綁定:

this._s = new Vue({ 
            data: {
                // 只有data中的數據纔是響應式
                state: options.state
            }
        })
複製代碼

5.三、getters實現

//實現getters原理
        let getters = options.getters || {}
        // console.log(getters);
        // this.getters = getters; //不是直接掛載到 getters上 這樣只會拿到整個 函數體
        this.getters = {};
        // console.log(Object.keys(getters))  // ["myAge","myName"]
        Object.keys(getters).forEach((getterName) => {
            // console.log(getterName)  // myAge
            // 將getterName 放到this.getters = {}中
            // console.log(this.state);
            Object.defineProperty(this.getters, getterName, {
                // 當你要獲取getterName(myAge)會自動調用get方法
                // 箭頭函數中沒有this               
                get: () => {
                    return getters[getterName](this.state)
                }
            })
        })
複製代碼

從上面源碼,咱們能夠看出Vuex的state狀態是響應式,是藉助vue的data是響應式,將state存入vue實例組件的data中;Vuex的getters則是藉助vue的計算屬性computed實現數據實時監聽。

5.四、mutations實現

let mutations = options.mutations || {}
        // console.log(mutations);
        this.mutations = {};
        Object.keys(mutations).forEach(mutationName=>{
            // console.log(mutationName);
            
            this.mutations[mutationName] = (payload) =>{
                this.mutations[mutationName](this.state,payload)
            }
        })
複製代碼

實現同步加: 動態效果圖:

5.五、actions實現

// actions的原理 
        let actions = options.actions || {}
        this.actions = {};
        forEach(actions,(actionName,value)=>{
            this.actions[actionName] = (payload)=>{
                value(this,payload)
            }
        })
複製代碼

5.六、commit dispatch的實現

commit(type,payload){
        this.mutations[type](payload)
    }
複製代碼
// type是actions的類型  
    dispatch=(type,payload)=>{
        this.actions[type](payload)
    }
複製代碼

6、原理總結:

Vuex是經過全局注入store對象,來實現組件間的狀態共享。在大型複雜的項目中(多級組件嵌套),須要實現一個組件更改某個數據,多個組件自動獲取更改後的數據進行業務邏輯處理,這時候使用vuex比較合適。假如只是多個組件間傳遞數據,使用vuex未免有點大材小用,其實只用使用組件間經常使用的通訊方法便可。

附加參考vuex源碼,能夠調試一下的

參考連接:www.cnblogs.com/hjson/p/105…

面試常見:blog.csdn.net/xu838209490…

相關文章
相關標籤/搜索