1. 程式人生 > 實用技巧 >【Vue】15 VueX

【Vue】15 VueX

【什麼是VueX?】

VueX是一個專門為Vue.js應用程式開發的狀態管理模式,

採用集中式儲存管理應用的所有元件狀態,

以相應的規則保證按照一種可預測的方式發生改變。

即把多個元件的變數統一放到一個地方管理

在專案中安裝Vuex

npm install vuex

新建store目錄和一個index.js

並寫入以下程式碼:

import Vue from 'vue';
import VueX from 'vuex';

Vue.use(VueX);

const store = new VueX.Store({
    state : {
        count : 0
    },
    mutations : {
        increment(state) {
            state.count
++; }, decrement(state) { state.count--; } } }); export default store;

其次,我們要讓所有的Vue元件,都能使用store,

就需要在main.js中引入,引入方式與router一樣

import Vue from 'vue'
import App from './App.vue'
import router from "./router"; // ./router/index.js 因為是index.js,可以預設不寫
import store from "./store"
; Vue.config.productionTip = false new Vue({ render: h => h(App), router, store }).$mount('#app');

在任意一個Vue元件中插值引入:

<template>
    <div>
        <h2>樣本的標題</h2>
        <p>樣本的標籤</p>
        <p>{{$store.state.count}}</p>
    </div>
</template
> <script> export default { name: "sample" } </script> <style scoped> </style>

可以看到這裡已經完全取出來了

然後再編寫兩個按鈕和對應的事件:

<template>
    <div>
        <h2>樣本的標題</h2>
        <p>樣本的標籤</p>
        <p> <button @click="decrease">減少</button> {{$store.state.count}}  <button @click="increase">增加</button> </p>
    </div>
</template>

<script>
    export default {
        name: "sample",
        methods : {
            decrease() {
                this.$store.commit("decrement");
            },
            increase() {
                this.$store.commit("increment");
            }
        }
    }
</script>

<style scoped>

</style>

檢視效果:

然後再主頁面也渲染這個變數:

可以發現,是一樣的:

就是為了一些公共變數而存在的

【State】

Vuex提出使用單一狀態樹,(單一資料來源),就是將一堆公共的資料放到一起去管理

state的意義類似Vue例項的data物件,所有的資料資訊存放state中,但是訪問不建議也像vue那樣直接引用

【Gettter】

我們需要從state中獲取一些經過改變後的資料,可以使用getter

store的index.js

import Vue from 'vue';
import VueX from 'vuex';

Vue.use(VueX);

const store = new VueX.Store({
    state : {
        count : 0,
        studentList : [
            { id : 1, name : "張三", age : 23, gender : true },
            { id : 2, name : "李四", age : 24, gender : true },
            { id : 3, name : "王五", age : 25, gender : true },
            { id : 4, name : "阿偉", age : 26, gender : true },
            { id : 5, name : "傑哥", age : 27, gender : true },
        ]
    },
    mutations : {
        increment(state) {
            state.count++;
        },
        decrement(state) {
            state.count--;
        }
    },
    getters : {
        getStudentByAge(state) {
            return state.studentList.filter(e => e.age > 24);
        }
    }
});

export default store;

在元件中可以通過this.$store.getters.xxx獲取

<p> {{$store.getters.getStudentByAge}} </p>

效果:

【Mutations】

用於對state中的資料進行修改,或者是傳值,類似vue例項的methods

呼叫mutations中的方法,需要這樣:

this.$store.commit('方法名稱',引數列表)

【Actions】

需要注意的是,我們不會在mutations進行非同步操作:【使用規範】

但是在某些特定需求的情況下必須使用:比如ajax非同步請求

這時候我們就可以使用actions處理:

作用就是為了代替mutations來完成這種功能

context引數,是和Store物件具有相同方法和屬性的物件

即我們可以使用context.commit呼叫mutations

import Vue from 'vue';
import VueX from 'vuex';

Vue.use(VueX);

const store = new VueX.Store({
    state : {
        count : 0,
        studentList : [
            { id : 1, name : "張三", age : 23, gender : true },
            { id : 2, name : "李四", age : 24, gender : true },
            { id : 3, name : "王五", age : 25, gender : true },
            { id : 4, name : "阿偉", age : 26, gender : true },
            { id : 5, name : "傑哥", age : 27, gender : true },
        ]
    },
    mutations : {
        increment(state) {
            state.count++;
        },
        decrement(state) {
            state.count--;
        }
    },
    getters : {
        getStudentByAge(state) {
            return state.studentList.filter(e => e.age > 24);
        }
    },
    actions : {
        increa(context) {
            context.commit('increment');
        }
    }
});

export default store;

呼叫actions的方法需要使用dispatch分發

<template>
    <div>
        <h2>樣本的標題</h2>
        <p>樣本的標籤</p>
        <p> <button @click="decrease">減少</button> {{$store.state.count}}  <button @click="increase">增加</button></p>
    </div>
</template>

<script>
    export default {
        name: "sample",
        methods : {
            decrease() {
                this.$store.commit("decrement");
            },
            increase() {
                // this.$store.commit("increment");
                this.$store.dispatch('increa');
            }
        }
    }
</script>

<style scoped>

</style>

其實對比發現,就是多一個action處理:

actions可用於非同步操作,即可以使用Promise,

在非同步操作中放入Promise,成功或者失敗後,呼叫對應函式

import Vue from 'vue';
import VueX from 'vuex';

Vue.use(VueX);

const store = new VueX.Store({
    state : {
        count : 0,
        studentList : [
            { id : 1, name : "張三", age : 23, gender : true },
            { id : 2, name : "李四", age : 24, gender : true },
            { id : 3, name : "王五", age : 25, gender : true },
            { id : 4, name : "阿偉", age : 26, gender : true },
            { id : 5, name : "傑哥", age : 27, gender : true },
        ]
    },
    mutations : {
        increment(state) {
            state.count++;
        },
        decrement(state) {
            state.count--;
        }
    },
    getters : {
        getStudentByAge(state) {
            return state.studentList.filter(e => e.age > 24);
        }
    },
    actions : {
        increa(context) {
            context.commit('increment');
        },
        mp(context) {
            return new Promise(resolve => {
                setTimeout(() => {
                    context.commit("decrement");
                    resolve();
                }, 1000);
            });
        }
    }
});

export default store;

元件這裡:

<template>
    <div>
        <h2>樣本的標題</h2>
        <p>樣本的標籤</p>
        <p> <button @click="decrease">減少</button> {{$store.state.count}}  <button @click="increase">增加</button></p>
    </div>
</template>

<script>
    export default {
        name: "sample",
        methods : {
            decrease() {
                // this.$store.commit("decrement");
                this.$store.dispatch('mp').then(res => {
                   alert("資料跟新完畢"); 
                });
            },
            increase() {
                // this.$store.commit("increment");
                this.$store.dispatch('increa');
            }
        }
    }
</script>

<style scoped>

</style>

每次點選減少按鈕就會晚一秒執行,然後再彈窗警告:

【Modules】

模組,vuex使用了單一狀態樹,當我們的狀態過多時,使用store管理可能臃腫,這時候可以按照模組區劃分vuex的store資料

當然,store還是可以統一管理module的

每個module即一個小的vuex,都具備上面的那些屬性【getters,state,actions . . .】

import Vue from 'vue';
import VueX from 'vuex';

Vue.use(VueX);

const user = {
    state : {
        studentList : [
            { id : 1, name : "張三", age : 23, gender : true },
            { id : 2, name : "李四", age : 24, gender : true },
            { id : 3, name : "王五", age : 25, gender : true },
            { id : 4, name : "阿偉", age : 26, gender : true },
            { id : 5, name : "傑哥", age : 27, gender : true },
        ],
        token : "",
        name : '',
        header : '',
    },
    getters : {
        getStudentByAge(state) {
            return state.studentList.filter(e => e.age > 24);
        }
    }
}

const baseData = {
    state : {
        count : 0,
    },
    mutations : {
        increment(state) {
            state.count++;
        },
        decrement(state) {
            state.count--;
        }
    },
    actions : {
        increa(context) {
            context.commit('increment');
        },
        mp(context) {
            return new Promise(resolve => {
                setTimeout(() => {
                    context.commit("decrement");
                    resolve();
                }, 1000);
            });
        }
    }
}

const store = new VueX.Store({
    modules : {
        user,
        baseData
    }
});



export default store;

元件中的呼叫也需要更改:

      <p> {{$store.state.baseData.count}} </p>
      <p> {{$store.getters.getStudentByAge}} </p>

如果再index.js有太多的模組,可以抽取成檔案,引入使用: