溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

vue怎么使用Vuex狀態(tài)管理模式

發(fā)布時間:2022-04-11 11:06:08 來源:億速云 閱讀:216 作者:iii 欄目:開發(fā)技術

這篇“vue怎么使用Vuex狀態(tài)管理模式”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內(nèi)容,內(nèi)容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“vue怎么使用Vuex狀態(tài)管理模式”文章吧。

    1、基于單向數(shù)據(jù)流問題而產(chǎn)生了Vuex

    單向數(shù)據(jù)流是vue 中父子組件的核心概念,props 是單向綁定的。當父組件的屬性值發(fā)生變化的時候,會傳遞給子組件發(fā)生相應的變化,從而形成一個單向下行的綁定,父組件的屬性改變會流向下行子組件中,但是反之,為了防止子組件無意間修改了父組件中的數(shù)據(jù)而影響到了其他的子組件的狀態(tài),vue 規(guī)定了從下往上的數(shù)據(jù)流是不允許的。當我們的應用遇到多個組件共享狀態(tài)時,單向數(shù)據(jù)流的簡潔性很容易被破壞:

    a、多個組件依賴于同一狀態(tài)。組件之間傳參變得特別繁瑣,并且兄弟組件之間狀態(tài)傳遞無能為力。

    b、來自不同視圖的行為需要變更同一狀態(tài)。 經(jīng)常會采用父子組件直接引用或者通過事件來變更和同步狀態(tài)的多份拷貝。

    我們?yōu)槭裁床话呀M件的共享狀態(tài)抽取出來,以一個全局單例模式管理呢?Vuex 是一個專為 Vue.js 應用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲管理應用的所有組件的狀態(tài),并以相應的規(guī)則保證狀態(tài)以一種可預測的方式發(fā)生變化。

    使用 Vuex 并不意味著你需要將所有的狀態(tài)放入 Vuex。雖然將所有的狀態(tài)放到 Vuex 會使狀態(tài)變化更顯式和易調試,但也會使代碼變得冗長和不直觀。如果有些狀態(tài)嚴格屬于單個組件,最好還是作為組件的局部狀態(tài)。應該根據(jù)你的應用開發(fā)需要進行權衡和確定。

    2、安裝及使用

    CDN 方式: <script src="...vuex.js"></script>
        NPM 方式: npm install vuex --save
        Yarn方式: yarn add vuex
        其他方式:項目初始化是引入依賴
        無論哪種方式都需要  Vue.use(Vuex)來安裝 Vuex

    3、核心及使用方法

    每一個 Vuex 應用的核心就是 store(倉庫)?!皊tore”基本上就是一個容器,它包含著你的應用中大部分的狀態(tài) vuex的Vuex 核心 State 、Getters 、Mutation、Action、Module。

    (1)State

    Vuex也使用了單一狀態(tài)樹來管理應用層級的全部狀態(tài)。唯一數(shù)據(jù)源。

    單一狀態(tài)樹能夠讓我們最直接的方式找到某個狀態(tài)的片段,而且在之后的維護和調試過程中,也可以非常方便的管理和維護。

    state存儲狀態(tài)類似于組件中data,在組件中訪問狀態(tài)經(jīng)常有兩種方法:分別為

    a、通過 this.$store.state.屬性 的方式來訪問狀態(tài),通常寫在computed計算屬性中,當然也可以直接通過插值表達式訪問;

    b、借助mapState 輔助函數(shù)。

    核心代碼如下:

    <div id="app">
                {{ mycount }}<br>
                直接插值表達式訪問
                {{ this.$store.state.count }}<br>
                {{ myinfoAge }}<br>
            </div>
            <script>
            import Vue from 'vue';
            import Vuex from 'vuex';
            import { mapState } from 'vuex'// 使用輔助函數(shù)一定記住引入
            const store = new Vuex.Store({
                // 存儲狀態(tài)數(shù)據(jù)
                state: {
                    count: 0,
                    info:{
                        name:"xiaoming",
                        age:18
                    }
                },
            )
            new Vue({ 
                el: '#app',
                store,
                computed:{
                    // a、計算屬性方式
                    mycount(){
                        return this.$store.state.count
                    },
                    // b、利用輔助函數(shù)賦值給對應變量,頁面可以直接使用該變量
                     ...mapState({
                        myinfoAge: (state) => state.info.age,
                    }),
                    // 當映射的計算屬性的名稱與 state 的子節(jié)點名稱相同時,我們也可以給 mapState 傳一個字符串數(shù)組。下面的簡化寫法相當于 info: (state) => state.info,
                    ...mapState(["info"]),
                }
            })
            </script>

    (2) Getters

    store的一個計算屬性,類比組件的計算屬性,getter 的返回值會根據(jù)它的依賴被緩存起來,且只有當它的依賴值發(fā)生了改變才會被重新計算,Getter 接受 state 作為其第一個參數(shù),在state中的數(shù)據(jù)發(fā)生改變,計算屬性重新計算

    Getters 的狀態(tài)存儲相當于組件中計算屬性,訪問方式有三種:

    a、通過屬性訪問

    b、通過方法訪問

    c、通過mapGetters 輔助函數(shù)訪問

    核心代碼如下:

    <div id="app">
               {{ myInfoLength }}<br>
               直接插值表達式訪問
               {{ this.$store.getters.infoLength }}<br>
               {{ myName }}<br>
               {{ infoLength }}
            </div>
            <script>
            import Vue from 'vue';
            import Vuex from 'vuex';
            import { mapGetters  } from 'vuex'// 使用輔助函數(shù)一定記住引入
            const store = new Vuex.Store({
                state: {
                    info:[
                        {name:"name1",age:18},
                        {name:"name2",age:28}
                    ]
                },
                // 存儲狀態(tài)數(shù)據(jù)
                getters: {
                    infoLength: (state) => {
                        return state.info.length;
                    },
                    getNameByAge: (state) => (age) => {
                        return state.info.find(item => item.age === age).name
                    }
                },
            )
            new Vue({ 
                el: '#app',
                store,
                computed:{
                    // a、通過屬性訪問
                    myInfoLength(){
                        return this.$store.getters.infoLength
                    }
                    // b、通過方法訪問
                    myName(){
                        return this.$store.getters.getNameByAge(18)
                    }
                    // c、mapGetters 輔助函數(shù)僅僅是將 store 中的 getter 映射到局部計算屬性
                    ...mapGetters(["infoLength"])
                }
            })
            </script>

    (3) Mutation

    前面state和getters兩個核心概念都是為了在store存儲數(shù)據(jù)和訪問數(shù)據(jù)的使用,Mutation則提供了對store中數(shù)據(jù)的修改功能,并且是唯一的更新方式,提交Mutation,Mutation主要包括兩部分:字符串的事件類型(type)和一個回調函數(shù)(handler),該回調函數(shù)的第一個參數(shù)就是state。

    在視圖組件中不能直接修改store容器中的狀態(tài),需要先在容器中注冊一個事件函數(shù),當需要更新狀態(tài)時候需要提交觸發(fā)該事件,同時可以向該事件傳遞參數(shù)。這里需要區(qū)別與組件內(nèi)v-model雙向綁定。提交事件方法有一下幾種:

    a、普通提交方式

    b、對象風格提交

    c、借助 mapMutations 輔助函數(shù)

    其核心代碼如下:

    <div id="app">
                <button @click="handleAdd">點我加一</button>
                <button @click="handleAddForNum">點我加加</button>
                <button @click="handleAddForObj">對象添加</button>
                <button @click="handleAddMap">對象添加</button>
            </div>
            <script>
            import Vue from 'vue';
            import Vuex from 'vuex';
            import { mapMutations  } from 'vuex'// 使用輔助函數(shù)一定記住引入
            const store = new Vuex.Store({
                state: {
                    count:1
                },
                mutations:{
                    // 注冊事件
                    addCount(state){
                        state.count ++
                    },
                    addCountForNum(state,num){
                        state.count += num
                    },
                    addCountForObj(state,payload){
                        state.count += payload.num
                    },
                    addMap(state){
                        state.count ++
                    }
                }
            )
            new Vue({ 
                el: '#app',
                store,
                methods:{
                    // a、普通提交方式
                    handleAdd(){
                        this.$store.commit('addCount')
                    },
                    handleAddForNum(){
                        this.$store.commit('addCountForNum',10)
                    },
                    // b、對象風格提交
                    handleAddForObj() {
                        this.$store.commit({ type: "addCountForObj", num: 100 });
                    },
                    // c、借助 mapMutations 輔助函數(shù)
                    ...mapMutations(["addMap"]),
                    handleAddMap(){
                        this.addMap()
                    }
                }
            })
            </script>

    Mutation 需遵守 Vue 的響應規(guī)則,Vuex 的 store 中的狀態(tài)是響應式的,那么當我們變更狀態(tài)時,監(jiān)視狀態(tài)的 Vue 組件也會自動更新。這也意味著 Vuex 中的 mutation 也需要與使用 Vue 一樣遵守一些注意事項:最好提前在你的 store 中初始化好所有所需屬性。當需要在對象上添加新屬性時,你應該使用 Vue.set(obj, 'newProp', 123), 或者以新對象替換老對象。例如,利用對象展開運算符 state.obj = { ...state.obj, newProp: 123 }

    注意:Mutation 必須是同步函數(shù)。在 mutation 中混合異步調用會導致你的程序很難調試。例如,當你調用了兩個包含異步回調的 mutation 來改變狀態(tài),你怎么知道什么時候回調和哪個先回調呢?

    (4) Action

     Action類似于Mutation, 但是是用來代替Mutation進行異步操作的.action 用于異步的修改state,它是通過muation間接修改state的。

     context是和store對象具有相同方法和屬性的對象.也就是說, 我們可以通過context去進行commit相關的操作, 也可以獲取context.state等.

     若需要異步操作來修改state中的狀態(tài),首先需要action來注冊事件,組件視圖在通過dispatch分發(fā)方式調用該事件,該事件內(nèi)部提交mutation中的事件完成改變狀態(tài)操作,總之,通過action這個中介來提交mutation中的事件函數(shù).分發(fā)事件方法如下:

    a、普通提交方式

     b、對象風格提交

     c、借助 mapActions 輔助函數(shù)

     核心代碼如下:

    <div id="app">
                <button @click="handleAdd">點我加一</button>
                <button @click="handleAddTen">點我加十</button>
                <button @click="handleAddForObj">對象添加</button>
                <button @click="handleAddMap">對象添加</button>
            </div>
            <script>
            import Vue from 'vue';
            import Vuex from 'vuex';
            import { mapMutations,mapActions  } from 'vuex'// 使用輔助函數(shù)一定記住引入
            const store = new Vuex.Store({
                state: {
                    count:1
                },
                // 注冊事件修改state狀態(tài)值
                mutations:{
                    addCount(state){
                        state.count ++
                    },
                    addCountForNum(state,num){
                        state.count += num
                    },
                    addCountForObj(state,payload){
                        state.count += payload.num
                    },
                    addMap(state){
                        state.count ++
                    }
                },
                // 注冊事件,提交給 mutation
                actions:{
                    addAction(context){
                        setTimeout(() => {
                            context.commit('addCount')
                        }, 1000)
                    },
                    addActionForNum(context,num){
                        setTimeout(() => {
                            context.commit('addCountForNum',num)
                        }, 1000)
                    },
                    addActionForObj(context,payload){
                        setTimeout(() => {
                            context.commit('addCountForObj',payload)
                        }, 1000)
                    },
                    addActionMap(context){
                        setTimeout(() => {
                            context.commit('addMap')
                        }, 1000)
                    }
                }
            )
            new Vue({ 
                el: '#app',
                store,
                methods:{
                    // a、普通提交方式
                    handleAdd(){
                        this.$store.dispatch('addAction')
                    },
                    handleAddTen(){
                        this.$store.dispatch('addActionForNum',10)
                    },
                    //  b、對象風格提交
                    handleAddForObj(){
                        this.$store.dispatch({
                            type: 'addActionForObj',
                            amount: 10
                        })
                    }
                    // 借助 mapActions 輔助函數(shù)
                    ...mapActions(["addActionMap"]),// 相當于...mapActions({addActionMap:"addActionMap"}) 
                    handleAddMap(){
                        this.addActionMap()
                    }
                }
            })

    組合 Action:組合多個 action,以處理更加復雜的異步流程.store.dispatch 可以處理被觸發(fā)的 action 的處理函數(shù)返回的 Promise,并且 store.dispatch 仍舊返回 Promise。一個 store.dispatch 在不同模塊中可以觸發(fā)多個 action 函數(shù)。在這種情況下,只有當所有觸發(fā)函數(shù)完成后,返回的 Promise 才會執(zhí)行。假設 getData() 和 getOtherData() 返回的是 Promise。

    actions: {
                async actionA ({ commit }) {
                    commit('gotData', await getData())
                },
                async actionB ({ dispatch, commit }) {
                    await dispatch('actionA') // 等待 actionA 完成
                    commit('gotOtherData', await getOtherData())
                }
            }

    (5)Modules

    Vuex允許我們將store分割成模塊(Module), 而每個模塊擁有自己的state、mutation、action、getters等

    4、Vuex和全局對象的不同

    (1)Vuex 的狀態(tài)存儲是響應式的。當 Vue 組件從 store 中讀取狀態(tài)的時候,若 store 中的狀態(tài)發(fā)生變化,那么相應的組件也會相應地得到高效更新。

    (2)你不能直接改變 store 中的狀態(tài)。改變 store 中的狀態(tài)的唯一途徑就是顯式地提交 (commit) mutation。這樣使得我們可以方便地跟蹤每一個狀態(tài)的變化,從而讓我們能夠實現(xiàn)一些工具幫助我們更好地了解我們的應用。

    以上就是關于“vue怎么使用Vuex狀態(tài)管理模式”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對大家有幫助,若想了解更多相關的知識內(nèi)容,請關注億速云行業(yè)資訊頻道。

    向AI問一下細節(jié)

    免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

    AI