# Vuex基本结构
> State中的数据 -render-> 渲染到组件上 -进行操作 dispatch-> action -commit-> mutation -mutate-> state
***如果使用Vuex,代码量会更多,代码逻辑会更加清晰***
## state (状态)
> state中保存了数据,可以放在各个组件中的数据,组件想要获取到数据,有两种方式
### 1. 直接使用
```HTML
```
### 2. 利用计算属性
```HTML
export default {
computed: {
state属性名 () {
return this.$store.state.state属性名
},
自定义名称 () {
return this.$store.state.state属性名
}
}
}
```
## getters (从state中获取新数据)
> getter的作用可以从state中动态获取数据,当state数据改变时,对应的getter也一样会改变。getter中有两个参数,一个是state,第二个是getter
```javascript
const store = new Vuex.Store({
state: {
},
getters: {
getter (state, getter) {
// 根据相关操作获取state以及其他getter中的数据
},
getterFn (state) {
// 返回一个函数体
return function (参数) {
// 返回数据
return 相关操作的到的数据
}
}
}
})
```
### 1. 直接使用
```HTML
```
### 2. 利用计算属性
```HTML
{{getter名字}}
{{getterFn(实参)}}
export default {
computed: {
getter名字 () {
return this.$store.getters.getter名字
},
getterFn () {
return this.$store.getters.getterFn
}
}
}
```
### mutations
> mutation只做纯粹的state数据修改操作,mutation需要被提交(commit)才能执行
***一般情况,state对应的都有mutation,有些不止一个***
```javascript
const store = new Vuex.Store({
state: {
},
mutations: {
mutation (state, payload) {
// 因为mutation是对state操作,所以有state属性,在commit时,可以提交数据,所以payload就是commit时提交的数据,可以是任意名字
}
}
})
```
### 在组件中 'commit' mutation (不是很符合规范)
```javascript
export default {
methods: {
clickHandler () {
this.$store.commit('mutation名字', '数据')
}
}
}
```
## actions
> action可以进行异步请求,将数据commit给mutation。action中还可以进行数据处理,将数据处理成mutation可以直接使用的数据
```javascript
const store = new Vuex.Store({
state: {
msg: "消息"
},
mutations: {
setMsg (state, msg) {
state.msg = msg
}
},
actions: {
getMsg (context, payload) {
// 根据相关的数据传递,将获取到payload发送给mutation
context.commit('setMsg', payload)
},
getMsg ({commit}, payload) {
commit('setMsg', payload)
}
}
})
```
> 在组件中 'dispatch' action
```javascript
export default {
methods: {
clickHandler () {
this.$store.dispatch('action名字')
}
}
}
```
### 获取到action异步是否执行完成
> 我们只需要在对应的action中return一个promise对象 (action执行结束后就是一个promise对象,有.then方法)
```javascript
{
actions: {
async action名字 () {
// return axios请求
try {
const res = await axios()
对结果进行处理
} catch (err) {
}
}
}
}
```
## 在vue-cli中使用Vuex
### 1. 在创建项目时选择Vuex组件即可
### 2. 自己创建环境
1. 创建一个项目
2. 安装Vuex
3. 在项目中src里新建文件夹store/index.js
4. 在index.js中写以下内容
```javascript
// 1 引入Vue及Vuex
import Vue from 'vue'
import Vuex from 'vuex'
// 2 调用Vue.use
Vue.use(Vuex)
// 3 创建Store的实例
const store = new Vuex.Store({
state: {},
getters: {},
mutations: {},
actions: {}
})
// 4 将store作为模块导出
export default store
```
5. 在main.js中引入store
```javascript
import store from './store/index'
new Vue({
store
})
```
# 辅助函数
> 解耦代码,可以让代码变得更简洁,只能在支持模块化的地方使用
* mapState
* mapGetters
* mapMutations
* mapActions
## mapState
```javascript
import { mapState } from 'vuex'
export default {
computed: mapState(), // 这样写不能添加新的针对该组件的computed
computed: {
...mapState(['state属性名', 'state属性名2']),
...mapState({
自定义名字: 'state属性名',
'state属性名': 'state属性名'
}),
// 相当于
自定义名字 () {
return this.$store.state.属性名
}
}
}
```
## mapGetters
```javascript
import { mapGetters } from 'vuex'
export default {
computed: mapGetters(), // 这样写不能添加新的针对该组件的computed
computed: {
...mapGetters(['getter名字']),
...mapGetters({
自定义名字: 'getter名字'
}),
// 相当于
自定义名字 () {
return this.$store.getters.getter名字
}
}
}
```
## mapMutations
> mapMutation和mapActions放在methods中,会被映射成一个方法
```javascript
import {mapMutations} from 'vuex'
export default {
methods: {
...mapMutations(['mutation名字']),
...mapMutations({
自定义名字: 'mutation名字'
}),
// 相当于
自定义名字 (data) {
this.$store.commit('mutation名字', data)
},
// 如果在提交前需要进行其他操作
自定义名字 () {
// 其他操作
this.mutation名字()
}
}
}
```
## mapActions
```javascript
import {mapActions} from 'vuex'
export default {
methods: {
...mapActions(['action名字']),
...mapActions({
自定义名字: 'actions名字'
}),
// 相当于
自定义名字 (data) {
this.$store.dispatch('action名字', data)
},
// 如果需要有其他操作
自定义名字 () {
// 其他操作
this.action名字()
}
}
}
```
***如果不理解,就先不要去看,学会如果使用this.$store***
# 模块
```javascript
const store = new Vuex.Store({
modules: {
module名字: {
// 每个模块都有自己独立state mutations actions getters 甚至还有modules
state: {},
getters: {},
actions: {},
mutations: {}
}
}
})
```
## 命名空间
> 我们可以给模块对象上添加namespaced: true
```javascript
const store = new Vuex.Store({
modules: {
module名字: {
namespaced: true
}
}
})
```
*命名空间: 可以给我们的模块的getter mutation action上添加前缀 ‘模块名/’ 便于和其他模块以及root进行区分*
## state
> 模块中的state放在rootState下的模块名中 this.$store.state.模块名.属性名
```javascript
const store = new Vuex.Store({
modules: {
module名字: {
namespaced: true,
state: {
msg: '模块中的数据'
}
}
}
})
// this.$store.state.module名字.msg namespaced属性对state没有任何影响
```
## getters
> 所有模块的getter都放置在一起,为了区分,我们添加namespaced: true,这个时候,对应模块的getter就变成了 ‘模块名/getter名字’ 使用时 `this.$store.getters['模块名/getter名字']`
```javascript
const store = new Vuex.Store({
modules: {
module名字: {
namespaced: true,
getters: {
getter (state, getters, rootState) {
// 只有在模块中的getter中才有第三个参数,rootState可以只从其他模块获取数据 state指的是当前模块的state
}
}
}
}
})
```
## mutations
> 所有模块的,mutation都放置在一起,为了区分,我们添加namespaced: true,这个时候,对应模块的,mutation就变成了 ‘模块名/,mutation名字’ 使用时 `this.$store.commit('模块名/mutation名字')`
如果是在action中使用
1. 当前模块的action
commit('mutation名字')
2. 其他模块的action
commit('模块名/mutation名字', null, {root: true})
## actions
> 所有模块的,action都放置在一起,为了区分,我们添加namespaced: true,这个时候,对应模块的,action就变成了 ‘模块名/,action名字’ 使用时 `this.$store.dispatch('模块名/action名字')`
## 辅助函数写法
```
const store = new Vuex.Store({
state: {
a: 1
},
modules: {
moduleA: {
state: {
b: 2,
c: 3
}
}
}
})
export default {
computed: {
...mapState(['a', 'moduleA/b', 'moduleA/c']),
...mapState('moduleA', ['b', 'c'])
}
}
```