Vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它提供了一种集中式存储管理应用的所有组件状态的方式,并以相应的规则保证状态只能按照预定的方式进行修改。Vuex 是 Vue.js 生态系统中的一部分,用于管理状态(State)。
五个核心
主要的核心概念包括:
- State(状态) : 包含应用级别的状态,是响应式的,即当状态发生变化时,所有使用该状态的地方都会自动更新。
- Getter(获取器) : 允许组件从状态中派生出一些值,类似于计算属性。
- Mutation(变更) : 是唯一允许修改状态的地方,它们是同步的。每个 mutation 都有一个字符串的事件类型(type)和一个回调函数,该回调函数就是实际进行状态修改的地方。
- Action(动作) : 类似于 mutation,不同在于 action 提交的是 mutation,而不是直接变更状态。可以包含异步操作。
- Module(模块) : 允许将 store 分割成模块,每个模块拥有自己的 state、getter、mutation、action。
使用 Vuex 的主要目的是解决 Vue.js 应用中组件之间共享状态的问题。在一个典型的 Vue.js 应用中,数据流是单向的,即从父组件传递到子组件。当应用的状态管理变得复杂时,组件之间的通信可能会变得困难,因为需要将状态通过多层组件传递。Vuex 提供了一种集中式管理状态的机制,允许组件直接从状态中读取数据,以及提交 mutation 来修改数据。这样,整个应用的状态就能够更加可控和可维护。
使用vuex
npm install vuex@next --sav
1-state
1- 把共享的状态放到state对象中
- 创建一个仓库实例
(store),把共享的状态放到state对象中
import { createStore } from 'vuex'
const store = createStore({
state () {
return {
isTabbarShow: true
}
}
})
export default store
//在main.js导入,并且使用
createApp(App)
.use(router)
.use(store) //使用仓库
.mount('#app')
2-直接使用
<template>
<div id="app">
{{ this.$store.state.name }}
{{ this.$store.state.age }}
</div>
</template>
3-mapState
通过
mapState把store映射到 组件的计算属性,就相当于组件内部有了state里的属性 知道这里为啥要用...展开吗使用对象展开运算符将此对象混入到外部对象中
computed: {
...mapState(['count', 'user'])
},
2-Mutation
1-修改状态
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。 当定义一个 mutation 时,你需要为其指定一个字符串的事件类型(type)以及一个回调函数(handler)。这个回调函数接受 state 作为第一个参数,其他参数(也就是 payload,如果有的话)作为后续参数
const store = createStore({
state: {
count: 0
},
mutations: {
// 事件类型为 'increment'
increment: function(state) {
// 回调函数接受 state 作为第一个参数
state.count++;
},
// 事件类型为 'incrementBy'
incrementBy: function(state, amount) {
// 回调函数接受 state 和额外的参数(payload)作为参数
state.count += amount;
}
}
});
2-this.$store.commit() 触发
- 在
methods中定义一个方法,在这个方法里面进行触发mutations中的方法
// 在组件中提交 'increment' mutation
methods: {
increment() { //不带参数
this.$store.commit('increment');
}
}
// 在组件中提交 'incrementBy' mutation,并传递额外的参数
methods: {
incrementByAmount(amount) {//带参数
this.$store.commit('incrementBy', amount);
}
}
3-mapMutation
import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
// `mapMutations` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
])
}
}
3-Getter
使用Getter 类似于计算属性,但是我们的数据来源是 Vuex 中的 state ,所以就使用 Vuex 中的 Getter 来完成,相当于对state
const store = createStore({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos (state) {
return state.todos.filter(todo => todo.done)
}
}
})
1-this.$store.getter[名称]
<template>
<div id="app">
{{ this.$store.getters.doneTodos }}
</div>
</template>
2-mapGetters
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// 使用对象展开运算符将 getter 混入 computed 对象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
}
4-Action
Action 同样也是用来处理任务,不过它处理的是异步任务,异步任务必须要使用 Action,通过 Action 触发 Mutation 间接改变状态,不能直接使用 Mutation 直接对异步任务进行修改
1-this.$store.dispatch()
this.$store.dispatch('increment')
2-mapActions
import { mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
// `mapActions` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
})
}
}
5-Modules
为了避免在一个复杂的项目 state 中的数据变得臃肿,Vuex 允许将 Store 分成不同的模块,每个模块都有属于自己的 state,getter,action,mutation
const moduleA = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... }
}
const store = createStore({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
1-命名空间
namespaced:true
如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。
computed: {
...mapState({
a: state => state.some.nested.module.a,
b: state => state.some.nested.module.b
}),
...mapGetters([
'some/nested/module/someGetter', // -> this['some/nested/module/someGetter']
'some/nested/module/someOtherGetter', // -> this['some/nested/module/someOtherGetter']
])
},
methods: {
...mapActions([
'some/nested/module/foo', // -> this['some/nested/module/foo']()
'some/nested/module/bar' // -> this['some/nested/module/bar']()
])
}