# vuex4 筆記
###### tags: `vue` `vuex` `vuex4`
## State
狀態容器,類似 data 存放資料用
```javascript=
const store = new Vuex.Store({
state: {
config: {}
}
})
```
## Getter
計算狀態,類似 computed
```javascript
const store = new Vuex.Store({
state: {
config: {
username: 'Yan',
money: 3000
},
posts: [
{
type: 1,
value: 10
},
{
type: 1,
value: 20
},
{
type: 2,
value: 30
}
]
},
getters: {
postType1(state) {
return state.posts.filter(post => post.type === 1);
},
postType1Max(state, getters) {
return Math.max(...getters.postType1.map(post => post.value));
},
info(state) {
return state.config.username + ' ' + state.config.money;
}
}
})
```
## Mutation
單一行為方法,行為單純,用於直接修改 state 使用(給 action 調用,不直接由組件內調用)
**※必須同步執行**
```javascript
const store = new Vuex.Store({
state: {
config: {}
},
mutations: {
updateConfig(state, newConfig) {
state.config = newConfig;
}
},
})
```
## Action
複合行為方法,行為具備邏輯判斷,用於組件內調用,禁止直接在 action 中修改 state,透過組合調用 mutations來改變狀態
**※可以異步執行**
```javascript
const fakeConfig = {
username: 'Yan',
money: 3000,
};
const store = new Vuex.Store({
state: {
config: {}
},
mutations: {
updateConfig(state, newConfig) {
state.config = newConfig;
}
},
actions: {
async getConfig(store) {
// commit(mutation 名稱, 欲修改傳入的新資料);
store.commit('updateConfig', fakeConfig);
}
},
})
```
## 組件調用
### 存取狀態
```html
<template>
<div>
存取state: {{ $store.state.config.username }}
存取getters: {{ $store.getters.info }}
</div>
</template>
```
```javascript
export default {
created() {
this.$store.dispatch('getConfig');
},
};
```
## Fake Api
```javascript
const userData = {
username: 'Yan',
money: 3000,
};
const fakeApi = function(ms) {
return new Promise(function(resolve) {
setTimeout(resolve, ms);
});
};
const useApi = async function(store, ms) {
store.commit('updateAPILoading', true);
await fakeApi(ms);
store.commit('updateAPILoading', false);
};
const store = new Vuex.Store({
state: {
userData: {},
APILoading: false,
},
mutations: {
updateAPILoading(state, bool) {
state.APILoading = bool;
},
updateUserData(state, newUserData) {
state.userData = newUserData;
},
},
actions: {
async getUserData(store) {
await useApi(store, 1000);
store.commit('updateUserData', userData);
},
},
});
new Vue({
el: '#app',
store,
created() {
this.$store.dispatch('getUserData');
},
})
```
### mapState / mapGetters
當一個組件需要獲取多種狀態時,可以使用,減少多餘的程式碼
```javascript
computed: {
// 本地 computed
getTodoById() {
return this.$store.getters.getTodoById(2);
},
// 使用展開運算符將 mapState 混合到外部物件中
...mapState([
'count',
]),
...mapState({
countAlias: 'count',
countPlusLocalState(state) {
return state.count + this.localCount;
},
countries: state => state.TSMarketData.countries, //用箭頭函數更簡潔
}),
// 使用展開運算符將 mapGetters 混合到外部物件中
...mapGetters([
'doneTodos',
'doneTodosCount',
]),
...mapGetters({
doneTodosAlias: 'doneTodos',
}),
},
};
```
### modules
- 如果在`A modules`想獲取`root modules`的方法
```javascript
dispatch('root modules方法', 參數, {root: true});
```
- 如果在`組件中`想獲取`A modules`的方法
```javascript
...mapActions('A modules', ['方法']),
...mapState('A modules', {
categories: state => state.indexConfig.categories,
hot_products: state => state.indexConfig.hot_products,
products: state => state.indexConfig.products
})
```
- 範本
```javascript
const state = () => ({
useApi,
});
const mutations = {
};
const actions = {
};
const getters = {};
export default {
namespaced: true,
state,
mutations,
actions,
getters
}
```