1. 程式人生 > >vuex的使用詳解

vuex的使用詳解

在SPA單頁面元件的開發中 Vue的vuex和React的Redux 都統稱為同一狀態管理。簡單的理解就是你在state中定義了一個數據之後,你可以在所在專案中的任何一個元件裡進行獲取、進行修改,並且你的修改可以得到全域性的響應變更。

vuex的五個物件

state:儲存狀態。也就是變數;
定義

new Vuex.Store({
    state: {
        allProducts: []
    }
    //...
})

元件中獲取

this.$store.state.allProducts

getters:和vue的computed差不多,是state資料的二次包裝;
定義

getters: {
    cartProducts(state, getters, rootState) 
        => (getters.allProducts.filter(p => p.quantity))
}

元件中獲取

this.$store.getters.cartProducts

mutations:這是vuex中唯一修改state的方式,但不支援非同步操作。第一個引數預設是state。
定義

mutations: {
    setProducts (state, products) {
        state.allProducts = products
    }
}

元件中使用

this.$store.commit('setProducts', {//..options})

actions:和mutations類似。用於提交mutation來改變狀態,而不直接變更狀態,可以包含任意非同步操作。
定義(shop為api)

actions: {
    getAllProducts ({ commit }, payload) {
        shop.getProducts((res) => {
            commit('setProducts', res)
        })
    }
}

元件中使用

this.$store.dispatch('getAllProducts', {//..payload})

modules:store的子模組,類似於名稱空間,用於專案中將各個模組的狀態分開定義和操作,便於維護。
定義

const moduleA = {
    state: { ... },
    mutations: { ... },
    actions: { ... },
    getters: { ... }
}

const moduleB = {
    state: { ... },
    mutations: { ... },
    actions: { ... }
}

const store = new Vuex.Store({
    modules: {
        a: moduleA,
        b: moduleB
    }
})

元件中使用

store.state.a //moduleA 的狀態
store.state.b //moduleB 的狀態

輔助函式

在元件中使用store中的資料或方法時,按照上面的說法,每次都要this.$store.的方式去獲取,有沒有簡單一點的方式呢?輔助函式就是為了解決這個問題

// 元件中註冊
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'

export default {
    computed: {
        // 陣列形式,當對映的計算屬性的名稱與 state 的子節點名稱相同時使用
        ...mapState(['allProducts'])
        // 物件形式,可重新命名 state 子節點名稱
        ...mapState({
            products: state => state.allProducts
        })
        // 下面為了簡便,均以陣列形式使用
        ...mapGetters(['cartProducts'])
    },
    methods: {
        ...mapMutations(['setProducts']),
        ...mapActions(['getAllProducts'])
    }
}

// 元件中使用
// 變數
this.allProducts
this.products
// 方法
this.setProducts()
this.getAllProducts()

vuex的使用:

├── index.html
├── main.js
├── components
└── store
    ├── index.js          # 我們組裝模組並匯出 store 的地方
    ├── state.js          # 跟級別的 state
    ├── getters.js        # 跟級別的 getter
    ├── mutation-types.js # 根級別的mutations名稱(官方推薦mutions方法名使用大寫)
    ├── mutations.js      # 根級別的 mutation
    ├── actions.js        # 根級別的 action
    └── modules
        ├── m1.js         # 模組1
        └── m2.js         # 模組2

1.首先在vue-cli專案中安裝 vuex :

npm install vuex --save

2.然後 在src檔案目錄下新建一個名為store的資料夾,在store資料夾裡新建js檔案
state.js:

const state = {
    name: 'weish',
    age: 22
};

export default state;

getters.js
(我們一般使用getters來獲取state的狀態,而不是直接使用state)

export const name = (state) => {
    return state.name;
}

export const age = (state) => {
    return state.age
}

export const other = (state) => {
    return `My name is ${state.name}, I am ${state.age}.`;
}

mutation-type.js
(我們會將所有mutations的函式名放在這個檔案裡):

export const SET_NAME = 'SET_NAME';
export const SET_AGE = 'SET_AGE';

mutations.js

import * as types from './mutation-type.js';

export default {
    [types.SET_NAME](state, name) {
        state.name = name;
    },
    [types.SET_AGE](state, age) {
        state.age = age;
    }
};

actions.js
(非同步操作、多個commit時)

import * as types from './mutation-type.js';

export default {
    nameAsyn({commit}, {age, name}) {
        commit(types.SET_NAME, name);
        commit(types.SET_AGE, age);
    }
};

modules–m1.js
(如果不是很複雜的應用,一般來講是不會分模組的)

export default {
    state: {},
    getters: {},
    mutations: {},
    actions: {}
};

index.js
組裝vuex

import vue from 'vue';
import vuex from 'vuex';
import state from './state.js';
import * as getters from './getters.js';
import mutations from './mutations.js';
import actions from './actions.js';
import m1 from './modules/m1.js';
import m2 from './modules/m2.js';
import createLogger from 'vuex/dist/logger'; // 修改日誌

vue.use(vuex);

const debug = process.env.NODE_ENV !== 'production'; // 開發環境中為true,否則為false

export default new vuex.Store({
    state,
    getters,
    mutations,
    actions,
    modules: {
        m1,
        m2
    },
    plugins: debug ? [createLogger()] : [] // 開發環境下顯示vuex的狀態修改
});

3.在vue例項中注入vuex

import store from './store/index.js';

new Vue({
  el: '#app',
  store,
  render: h => h(App)
});

應用場景

購物車
商品增減時,庫存變化,購物車列表和金額變化
清空購物車時,所有資料還原