当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏 ==> vuex
1.state
State 提供唯一的公共数据源,所有共享的数据都要统一放到 Store 的 State 中进行存储。
// 创建store数据源,提供唯一公共数据
const store = new Vuex.Store({
state: { count: 0 }
})
组件访问 State 中数据的第一种方式:
this.$store.state.全局数据名称
组件访问 State 中数据的第二种方式:
// 1. 从 vuex 中按需导入 mapState 函数
import { mapState } from 'vuex'
// 2. 将全局数据,映射为当前组件的计算属性
computed: {
...mapState(['count'])
}
2.Mutation
Mutation 用于变更 Store中 的数据。
① 只能通过 mutation 变更 Store 数据,不可以直接操作 Store 中的数据。
② 通过这种方式虽然操作起来稍微繁琐一些,但是可以集中监控所有数据的变化。
// 定义 Mutation
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
add(state) {
// 变更状态
state.count++
}
}
})
// 触发 mutations 的第一种方式
methods: {
handle1() {
this.$store.commit('add')
}
}
// 触发 mutations 的第二种方式
import { mapState, mapMutations } from "vuex";
methods: {
hehe() {
this.changeName(this.list);
},
...mapMutations(["changeName"])
}
// 定义Mutation
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
addN(state, step) {
// 变更状态
state.count += step
}
}
})
// 触发mutation 传参
methods: {
handle2() {
// 在调用 commit 函数,
// 触发 mutations 时携带参数
this.$store.commit('addN', 3)
}
}
3.Action
Action用于处理异步任务。
如果通过异步操作变更数据,必须通过 Action,而不能使用 Mutation,但是在 Action 中还是要通过触发
Mutation 的方式间接变更数据
// 定义 Action
const store = new Vuex.Store({
// ...省略其他代码
mutations: {
add(state) {
state.count++
}
},
actions: {
addAsync(context) {
setTimeout(() => {
context.commit('add')
}, 1000)
}
}
})
// 触发 actions 的第一种方式
methods: {
handle() {
this.$store.dispatch('addAsync')
}
}
// 触发 actions 的第二种方式
import { mapActions } from "vuex"
methods:{
...mapActions(['getAsyncCount'])
}
<button @click="getAsyncCount(111)">+异步</button>
// 定义 Action
const store = new Vuex.Store({
mutations: {
addN(state, step) {
state.count += step
}
},
actions: {
addNAsync(context, step) {
setTimeout(() => {
context.commit('addN', step)
}, 1000)
}
}
})
// 触发 Action
methods: {
handle() {
// 在调用 dispatch 函数,
this.$store.dispatch('addNAsync', 5)
}
}
4.Getter
Getter用于对 Store 中的数据进行加工处理形成新的数据。
① Getter 可以对 Store 中已有的数据加工处理之后形成新的数据,类似 Vue 的计算属性。
② Store 中数据发生变化,Getter 的数据也会跟着变化。
// 定义 Getter
const store = new Vuex.Store({
state: {
count: 0
},
getters: {
showNum: state => {
return '当前最新的数量是【'+ state.count +'】'
}
}
})
// 使用 getters 的第一种方式:
this.$store.getters.名称
// 使用 getters 的第二种方式:
computed: {
...mapGetters(['filterList'])
}
5.Module
由于应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。需要解决这问题,因此Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。
对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态对象。
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 的状态
对于模块内部的 action,局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState
const moduleA = {
actions: {
incrementIfOddOnRootSum ({ state, commit, rootState }) {
if ((state.count + rootState.count) % 2 === 1) {
commit('increment')
}
}
}
}
对于模块内部的 getter,根节点状态会作为第三个参数暴露出来
const moduleA = {
getters: {
sumWithRootCount (state, getters, rootState) {
return state.count + rootState.count
}
}
}