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)
});
應用場景
購物車
商品增減時,庫存變化,購物車列表和金額變化
清空購物車時,所有資料還原