Vuex原理解析 2021-03-22

一砸狞、前言
自從學(xué)習(xí)了VUE框架,其中必不可少的會用到vuex這個核心插件,而且在做項目的時候,基本都會使用,可能你會使用vuex狀態(tài)管理喻频,但是對vuex原理存在著或多或少的的疑惑或不解脓恕,這篇文章就針對vuex原理進(jìn)行研究膜宋,希望能幫助到大家,如果有不準(zhǔn)確的地方炼幔,大家多多指教秋茫。。乃秀。

二肛著、Vuex是什么?
Vuex是專門為Vue服務(wù)跺讯,用于管理頁面的數(shù)據(jù)狀態(tài)枢贿、提供統(tǒng)一數(shù)據(jù)操作的生態(tài)系統(tǒng),相當(dāng)于數(shù)據(jù)庫mongoDB刀脏,MySQL等局荚,任何組件都可以存取倉庫中的數(shù)據(jù)。其中vuex類似的 還是有Redux,Redux大多用于React,針對Redux后續(xù)在做補(bǔ)充愈污,現(xiàn)在就讓我們好好了解下Vuex到底是個啥東西耀态?

概念理解性(必讀
Vuex采用MVC模式中的Model層,規(guī)定所有的數(shù)據(jù)必須通過action—>mutaion—>state這個流程進(jìn)行來改變狀態(tài)的暂雹。再結(jié)合Vue的數(shù)據(jù)視圖雙向綁定實現(xiàn)頁面的更新首装。統(tǒng)一頁面狀態(tài)管理,可以讓復(fù)雜的組件交互變的簡單清晰杭跪,同時在調(diào)試時也可以通過DEVtools去查看狀態(tài)仙逻。

在當(dāng)前前端的spa模塊化項目中不可避免的是某些變量需要在全局范圍內(nèi)引用,此時父子組件的傳值涧尿,子父組件間的傳值系奉,兄弟組件間的傳值成了我們需要解決的問題。雖然vue中提供了props(父傳子)commit(子傳父)兄弟間也可以用localstorage和sessionstorage姑廉。但是這種方式在項目開發(fā)中帶來的問題比他解決的問題(難管理缺亮,難維護(hù),代碼復(fù)雜庄蹋,安全性低)更多。vuex的誕生也是為了解決這些問題迷雪,從而大大提高我們vue項目的開發(fā)效率限书。

拋出問題
使用Vuex只需執(zhí)行 Vue.use(Vuex),并在Vue的配置中傳入一個store對象的示例章咧,store是如何實現(xiàn)注入的倦西?
state內(nèi)部是如何實現(xiàn)支持模塊配置和模塊嵌套的?
在執(zhí)行dispatch觸發(fā)action(commit同理)的時候赁严,只需傳入(type, payload)扰柠,action執(zhí)行函數(shù)中第一個參數(shù)store從哪里獲取的粉铐?
如何區(qū)分state是外部直接修改,還是通過mutation方法修改的卤档?

三蝙泼、vue和vuex關(guān)系

看一下這個vue響應(yīng)式的例子,vue中的data 劝枣、methods汤踏、computed,可以實現(xiàn)響應(yīng)式舔腾。

視圖通過點(diǎn)擊事件溪胶,觸發(fā)methods中的increment方法,可以更改state中count的值稳诚,一旦count值發(fā)生變化哗脖,computed中的函數(shù)能夠把getCount更新到視圖。

<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這個響應(yīng)式的例子有什么關(guān)系呢扳还?

我們可以用vuex實現(xiàn)和vue同樣的響應(yīng)式功能才避。
1
其實他們原理時一樣的,vuex中也有四個屬性值:state普办、getters工扎、mutations、actions衔蹲。肢娘。

在沒有actions的情況下:

數(shù)據(jù):state --> data
獲取數(shù)據(jù):getters --> computed
更改數(shù)據(jù):mutations --> methods
視圖通過點(diǎn)擊事件,觸發(fā)mutations中方法舆驶,可以更改state中的數(shù)據(jù)橱健,一旦state數(shù)據(jù)發(fā)生更改,getters把數(shù)據(jù)反映到視圖沙廉。

那么actions,可以理解處理異步拘荡,而單純多加的一層。

既然提到了mutions actions這時候 就不得不提commit撬陵,dispatch這兩個有什么作用呢珊皿?

在vue例子中,通過click事件巨税,觸發(fā)methods中的方法蟋定。當(dāng)存在異步時,而在vuex中需要dispatch來觸發(fā)actions中的方法草添,actions中的commit可以觸發(fā)mutations中的方法驶兜。同步,則直接在組件中commit觸發(fā)vuex中mutations中的方法。

四抄淑、vuex實現(xiàn)
下面我們看下vuex中能像vue中實現(xiàn)改變狀態(tài)屠凶,更新視圖的功能:

Vuex.js

const store =  new Vuex.Store({
    
    state: {
        count: 0
    },
    
    //state的值只能通過mutations來修改
    mutations: {
        increment(state) {
            state.count++
        }
    },
    
   //this.$store.commit("increment")觸發(fā)mutations中函數(shù)"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>
            <!-- 有時候不能直接 強(qiáng)制使用store里面的狀態(tài) this.$store.state.count -->
            {{this.$store.getters.getCount}}
    </div>
    </template>
     
    <script>
    export default {
        methods: {
        increment(){
                //this.$store.dispatch("increment")觸發(fā)actions函數(shù)"increment"
                this.$store.dispatch("increment")
            }
        }
    }
    </script>

五、源碼分析:
現(xiàn)在我們已經(jīng)了解vuex能實現(xiàn)和像vue雙向數(shù)據(jù)綁定–更新試圖的功能肆资,下面我們重點(diǎn)說說vuex源碼的實現(xiàn):

5.1矗愧、store注入組件install方法
解答問題:vuex的store是如何注入到組件中的?

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

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

當(dāng)ues(Vuex)時候迅耘,會調(diào)用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機(jī)制纽哥,借助vue組件的生命周期 鉤子 beforeCreate 完成的。即 每個vue組件實例化過程中栖秕,會在 beforeCreate 鉤子前調(diào)用 vuexInit 方法春塌。

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

5.2簇捍、new vue實現(xiàn)雙向數(shù)據(jù)綁定:

        this._s = new Vue({ 
            data: {
                // 只有data中的數(shù)據(jù)才是響應(yīng)式
                state: options.state
            }
        })

5.3只壳、getters實現(xiàn)

 //實現(xiàn)getters原理
        let getters = options.getters || {}
        // console.log(getters);
        // this.getters = getters; //不是直接掛載到 getters上 這樣只會拿到整個 函數(shù)體
        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, {
                // 當(dāng)你要獲取getterName(myAge)會自動調(diào)用get方法
                // 箭頭函數(shù)中沒有this               
                get: () => {
                    return getters[getterName](this.state)
                }
            })
        })

從上面源碼,我們可以看出Vuex的state狀態(tài)是響應(yīng)式暑塑,是借助vue的data是響應(yīng)式吼句,將state存入vue實例組件的data中;Vuex的getters則是借助vue的計算屬性computed實現(xiàn)數(shù)據(jù)實時監(jiān)聽事格。

5.4惕艳、mutations實現(xiàn)

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)
            }
        })

實現(xiàn)同步加:
動態(tài)效果圖:

5.5、actions實現(xiàn)

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

5.6驹愚、commit dispatch的實現(xiàn)

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

六远搪、原理總結(jié):
Vuex是通過全局注入store對象,來實現(xiàn)組件間的狀態(tài)共享逢捺。在大型復(fù)雜的項目中(多級組件嵌套)谁鳍,需要實現(xiàn)一個組件更改某個數(shù)據(jù),多個組件自動獲取更改后的數(shù)據(jù)進(jìn)行業(yè)務(wù)邏輯處理劫瞳,這時候使用vuex比較合適倘潜。假如只是多個組件間傳遞數(shù)據(jù),使用vuex未免有點(diǎn)大材小用志于,其實只用使用組件間常用的通信方法即可涮因。

附加參考vuex源碼,可以調(diào)試一下的

參考鏈接:https://www.cnblogs.com/hjson/p/10500770.html

面試常見:https://blog.csdn.net/xu838209490/article/details/80334283
————————————————
版權(quán)聲明:本文為CSDN博主「凌晨四點(diǎn)半er」的原創(chuàng)文章恨憎,遵循CC 4.0 BY-SA版權(quán)協(xié)議蕊退,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_44667072/article/details/101164766

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末憔恳,一起剝皮案震驚了整個濱河市瓤荔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌钥组,老刑警劉巖输硝,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異程梦,居然都是意外死亡点把,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門屿附,熙熙樓的掌柜王于貴愁眉苦臉地迎上來郎逃,“玉大人,你說我怎么就攤上這事挺份“玻” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵匀泊,是天一觀的道長优训。 經(jīng)常有香客問我,道長各聘,這世上最難降的妖魔是什么揣非? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮躲因,結(jié)果婚禮上早敬,老公的妹妹穿的比我還像新娘。我一直安慰自己毛仪,他們只是感情好搁嗓,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著箱靴,像睡著了一般腺逛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上衡怀,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天棍矛,我揣著相機(jī)與錄音,去河邊找鬼抛杨。 笑死够委,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的怖现。 我是一名探鬼主播茁帽,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼玉罐,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了潘拨?” 一聲冷哼從身側(cè)響起吊输,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎铁追,沒想到半個月后季蚂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡琅束,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年扭屁,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涩禀。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡料滥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出艾船,到底是詐尸還是另有隱情幔欧,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布丽声,位于F島的核電站礁蔗,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏雁社。R本人自食惡果不足惜浴井,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望霉撵。 院中可真熱鬧磺浙,春花似錦、人聲如沸徒坡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽喇完。三九已至伦泥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間锦溪,已是汗流浹背不脯。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留刻诊,地道東北人防楷。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像则涯,于是被迫代替她去往敵國和親复局。 傳聞我的和親對象是個殘疾皇子冲簿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容

  • vue是目前最流行的前端框架之一,vuex則是一個狀態(tài)管理器亿昏,負(fù)責(zé)管理vue中各個對象的狀態(tài)變化并同步渲染到頁面上...
    老鼠AI大米_Java全棧閱讀 7,015評論 0 10
  • 1.vuex是什么民假?怎么使用?哪種功能場景使用它龙优? Vuex 是一個專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式...
    猴逃逃閱讀 837評論 0 2
  • Vuex五個概念的簡單理解彤断。 1.State 保存共享狀態(tài)信息的地方。2.Getters 類似我們單個組件中的計算...
    似朝朝我心閱讀 847評論 0 6
  • Vuex 是什么? Vuex 是一個專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式它采用集中式存儲管理應(yīng)用的所有組...
    coderlion閱讀 363評論 0 0
  • 為什么需要Vuex 通常 Vue 項目中的數(shù)據(jù)通信易迹,我們通過以下三種方式就可以解決宰衙,但是隨著項目多層嵌套的組件增加...
    尤小小閱讀 1,071評論 1 5