先給出官網地址
一、什麼是vuex
官方解釋: Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化
二、爲什麼要用vuex
vuex主要是是做數據交互,父子組件傳值可以很容易辦到,但是兄弟組件間傳值(兄弟組件下又有父子組件),或者大型spa單頁面框架項目,頁面多並且一層嵌套一層的傳值,異常麻煩,用vuex來維護共有的狀態或數據會顯得得心應手。
三、安裝vuex
npm install --save vuex
四、配置vuex
【1】在src文件夾下新增一個store文件夾,裏面添加一個index.js文件
【2】在main.js文件中引入store文件下的index.js
// main.js內部對vuex的配置
import store from '@/store/index.js'
new Vue({
el: '#app',
store, // 將store暴露出來
template: '<App></App>',
components: { App }
});
【3】store文件下的index.js配置
import Vue from 'vue'; //首先引入vue
import Vuex from 'vuex'; //引入vuex
Vue.use(Vuex)
export default new Vuex.Store({
state: {
// state 類似 data
//這裏面寫入數據
},
getters:{
// getters 類似 computed
// 在這裏面寫個方法
},
mutations:{
// mutations 類似methods
// 寫方法對數據做出更改(同步操作)
},
actions:{
// actions 類似methods
// 寫方法對數據做出更改(異步操作)
}
})
五、超簡單案例
在store中定義商品的原價,計算折扣價,根據用戶輸入的數量和商品原價計算出總價
【1】我們約定store中的數據是以下形式
import Vue from 'vue'; //首先引入vue
import Vuex from 'vuex'; //引入vuex
Vue.use(Vuex)
export default new Vuex.Store({
state: {
price: 100, // 原價
total: '', // 總價
},
getters:{
// 折扣價
discount(state, getters) {
return state.price*0.8
}
},
mutations:{
// 計算總價:第一個參數爲默認參數state, 後面的參數爲頁面操作傳過來的參數
getTotal(state, n) {
return state.total = state.price * n;
}
},
actions:{
// 這裏主要是操作異步操作的,使用起來幾乎和mutations方法一模一樣
// 除了一個是同步操作,一個是異步操作,一個使用commit調用,一個使用dispatch調用
// 這裏就不多介紹了,有興趣的可以自己去試一試,
// 比如你可以用setTimeout去嘗試一下
}
})
【2】在頁面中使用store中的數據
<template>
<div>
<p>原價:{{price}}</p>
<p>8折:{{discount}}</p>
<p>數量:<input type="text" v-model="quantity"></p>
<p>總價:{{total}}</p>
<button @click="getTotal">計算總價</button>
</div>
</template>
<script>
export default {
data() {
return {
quantity: 0,
}
},
computed: {
price() {
return this.$store.state.price
},
discount() {
return this.$store.getters.discount
},
total() {
return this.$store.state.total
}
},
mounted() {
},
methods: {
getTotal() {
this.$store.commit('getTotal', this.quantity)
}
},
}
</script>
【3】頁面效果
六、mutation提交載荷
你可以向 store.commit 傳入額外的參數,即 mutation 的 載荷(payload)
store.commit('increment', 10)
// ...
mutations: {
increment (state, n) {
state.count += n
}
}
在大多數情況下,載荷應該是一個對象,這樣可以包含多個字段並且記錄的 mutation 會更易讀
store.commit('increment', {
amount: 10
})
// ...
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}
提交 mutation 的另一種方式是直接使用包含 type 屬性的對象
store.commit({
type: 'increment',
amount: 10
})
// ...
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}
七、輔助函數mapState、mapGetters、mapMutations、mapActions
【1】mapState
當一個組件需要獲取多個狀態時候,將這些狀態都聲明爲計算屬性會有些重複和冗餘。爲了解決這個問題,我們可以使用mapState輔助函數幫助我們生成計算屬性,有了對象展開運算符... 我們可以將mapState函數與頁面局部的計算屬性混合使用,修改上面的案例如下
import { mapState } from 'vuex'
export default {
computed: {
// 當前頁面的計算屬性
localCoputed() {
return 'test'
},
// 使用對象展開運算符將 state 混入 computed 對象中
...mapState([
'price',
'total'
]),
},
如果你想將一個 state屬性另取一個名字,使用對象形式:
...mapState({
goodsPrice: 'price',
priceTotal: 'total'
}),
【2】mapGetters
mapGetters輔助函數僅僅是將 store 中的 getter 映射到局部計算屬性
import { mapState, mapGetters } from 'vuex'
export default {
computed: {
// 當前頁面的計算屬性
localCoputed() {
return 'test'
},
// 使用對象展開運算符將 state 混入computed 對象中
...mapState([
'price',
'total'
]),
// 使用對象展開運算符將 getter 混入 computed 對象中
...mapGetters([
'discount'
]),
},
如果你想將一個 getter 屬性另取一個名字,使用對象形式:
...mapGetters({
priceDiscount: 'discount'
}),
【3】mapMutations
mapMutations輔助函數將組件中的 methods 映射爲store.commit調用, 修改上面案例
import { mapMutations } from 'vuex'
export default {
methods: {
// 使用對象展開運算符將 mutation 混入 methods 對象中
...mapMutations([
'getTotal',
]),
},
如果你想將一個 mutation 另取一個名字,使用對象形式:
...mapMutations({
allTotal: 'getTotal',
}),
那麼,問題來了,之前我們也說過,mutations對象中的方法是可以傳參的(payload),那麼在mapMutations中如何傳參呢?
其實很簡單:像寫一般的方法一樣,直接在方法名後面的( )中將需要傳遞的參數寫進去
<button @click="getTotal(quantity)">計算總價</button>
...mapMutations([
'getTotal', // 將this.getTotal(quantity)映射爲this.$store.commit('getTotal', quantity)
]),
【4】mapActions
使用 mapActions 輔助函數將組件的 methods 映射爲store.dispatch調用
import { mapActions} from 'vuex'
export default {
methods: {
// 使用對象展開運算符將 action 混入 methods 對象中
...mapActions([
'increment', // 將this.increment()映射爲this.$store.dispatch('increment')
]),
},
如果你想將一個 action 另取一個名字,使用對象形式:
...mapActions({
add: 'increment',
}),
八、Module介紹
在項目比較複雜的時候,數據全部寫在一個state 方法全部集中一個mutations中,將會使我們的文件顯得太過於臃腫,而且不易維護,那怎麼辦呢?還是那句話辦法總比問題多,vuex爲我們提供了module這樣一個模塊的概念。我們可以利用它來根據我們個個組件或者頁面所需要的數據一一分割成不同的模塊,看下面示例
const moduleA = {
state: {},
mutations: {},
actions: {},
getters: {}
}
const moduleB = {
state: {},
mutations: {},
actions: {},
getters: {}
}
export default new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
// 在各自的模塊內部使用
state.price // 這種使用方式和單個使用方式一樣,直接使用就行
//在組件中使用
store.state.a.price // 先找到模塊的名字,再去調用屬性
store.state.b.price // 先找到模塊的名字,再去調用屬性