1. vuex是什麼?
Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的所有組件的狀態。
白話:vuex就是幫我們存儲一下多個組件共享的數據,方便我們對其讀取和更改。
2. State
官方解釋:Vuex使用單一狀態樹,用一個對象就包含了全部的應用層次狀態。它便作爲一個唯一的數據源而存在。這也就意味着, 每個應用將僅僅包含一個store實例。
白話:組件中所要共享的數據,我們就會抽取一個store,而state即是我們可以共享的數據。
3. Mutations
更改Vuex的store中的狀態的唯一方法是提交mutation。
Vuex中的mutation非常類似於事件:每個mutation都有一個字符串的事件類型和一個回調函數。
這個回調函數就是我們實際進行狀態更改的地方。並且它會接受state第一個參數。
白話:可以理解爲更改state的唯一途徑就是mutation(同步)
4. Actions
類似於Mutation,不同在於:
-
Action提交的是mutation,而不是直接更改狀態
-
Action可以包含任意一步操作
白話:Actions也可以更改state,但是是通過commit,提交到mutation,不直接更改(異步)
5. Getters
Vuex 允許我們在 store 中定義getter
(可以認爲是 store 的計算屬性)。
就像計算屬性 computed
一樣,getter
的返回值會根據它的依賴被緩存起來。
且只有當它的依賴值發生了改變纔會被重新計算。
6. mapState
是一個輔助函數,當一個組件需要獲取多個狀態時候,將這些狀態都聲明爲計算屬性會有些重複和冗餘。
爲了解決這個問題,我們可以使用 mapState 輔助函數幫助我們生成計算屬性。
白話:即幫我們獲取對應的state值
7. mapAction
是一個輔助函數,個人覺得比 dispatch 使用起來方便,主要是創建組件方法分發action,推薦使用。
關鍵實操來啦!
1. 安裝
npm install vuex --save
2. 目錄結構 (此項目使用是vue-admin-template腳手架)
用例鏈接:https://github.com/yzren/Vuex.git
- build
- node-modules
- public
- src
- api
- components
- layout
- components
- appMain.vue
- child.vue
- router
- store
- modules
- app.js (我們例子中寫vuex相關信息文件)
- index.js
- app.vue
- main.js
3. 簡單實例
-
在store文件夾下modules文件夾下添加app.js文件
app.js文件內容:
const state = {
count: 1
}
const mutations = {
SET_ADD_COUNT: (state) => {
state.count++
},
SET_SUBTRACT_COUNT: (state) => {
state.count--
}
}
const actions = {
// 加
add({ commit }) {
commit('SET_ADD_COUNT')
},
// 減
subtract({ commit }) {
commit('SET_SUBTRACT_COUNT')
}
}
export default {
// namespaced: true,
state,
mutations,
actions
}
2.在store文件夾下新建index.js文件,index內容:
import Vue from 'vue'
import Vuex from 'vuex'
import app from './modules/app'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
app //封裝的存放state下count的方法
}
})
export default store
3.在main.js中引入store文件
import store from './store'
...
new Vue({
el: '#app',
router,
store,
render: h => h(App)
})
-
具體到組件中使用,我們以layout內組件爲例子
AppMain.vue
<template>
<section class="app-main">
<h2>父親組件</h2>
<p>count計算結果 :
<strong>{{ count }}</strong>
</p>
<el-button size="small" @click="addFn">+</el-button>
<el-button size="small" @click="subtractFn">-</el-button>
<div>
<child />
</div>
</section>
</template>
<script>
import { mapState, mapActions } from 'vuex'
import Child from './chind'
export default {
name: 'AppMain',
components: {
Child
},
computed: {
...mapState({
count: state => state.app.count
})
},
methods: {
...mapActions(['add', 'subtract']),
addFn() {
this.add()
},
subtractFn() {
this.subtract()
}
}
}
</script>
...
child.vue
<template>
<section class="app-main">
<h2>子組件</h2>
<p>count計算結果 :
<strong>{{ count }}</strong>
</p>
<el-button size="small" @click="addFn">+</el-button>
<el-button size="small" @click="subtractFn">-</el-button>
</section>
</template>
<script>
import { mapState, mapActions } from 'vuex'
export default {
name: 'Child',
computed: {
...mapState({
//引用count
count: state => state.app.count
})
},
methods: {
//分發action,即引入之後,就能通過【this.store中的方法名】,
//調用store內相對應的方法,
//此例調用的就是action的add和subtract方法
...mapActions(['add', 'subtract']),
addFn() {
this.add()
},
subtractFn() {
this.subtract()
}
}
}
</script>
...
4. 異步實例
主要展示store內文件相關代碼,其調用於以上簡單實力類似
//封裝的axios文件
import http from '@common/http';
//封裝的需要調用後端的接口文件
import { api } from '@common/config';
//共享的數據
const state = {
listData: {}
};
const actions = {
// 獲取
gitTestList({state, commit}, params) {
// 緩存已請求數據
if (state.listData[params.id]) {
return Promise.resolve(state.listData[params.id]);
}
return http.get(api.testApi, { params, notLoading: true }).then(res => {
commit('SET_TEST_LIST', res.data);
return res.data;
});
}
};
const mutations = {
//設置列表相應信息
SET_TEST_LIST(state, data) {
state.listData[data.id] = data;
}
};
export default {
state,
actions,
mutations
};