1. 什么是Vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式和库。它解决了在大型 Vue.js 应用程序中共享和管理状态的问题,使得状态管理变得更加简单、可预测和可维护。
在 Vue.js 应用中,组件之间的通信可以通过 props 和事件进行,但随着应用的复杂性增加,组件之间的状态共享和状态变更管理变得困难。Vuex 提供了一种集中式的状态管理方案,将所有组件的状态存储在一个单一的地方,称为 "store"。
Vuex 的核心概念包括:
- State(状态): Vuex 使用一个单一的状态树(state tree)来存储应用的所有状态。这个状态树是响应式的,任何组件可以直接访问和监听状态的变化。
- Getters(获取器): Getters 允许组件从 Vuex store 中获取状态,并对其进行计算和过滤。类似于组件中的计算属性,Getters 可以缓存计算结果,避免不必要的重复计算。
- Mutations(变更): Mutations 是修改状态的唯一方式。它们是同步的事务,用于改变状态树中的数据。Mutations 是通过提交 (commit) 来触发,确保状态的变更是可追踪的。
- Actions(动作): Actions 用于处理异步操作和复杂的业务逻辑。它们可以包含多个 Mutations 的提交,用于改变状态。Actions 可以被组件调用,触发异步操作,并提交 Mutations 来改变状态。
- Modules(模块): Modules 允许将 Vuex store 分割成模块,每个模块拥有自己的 state、getters、mutations 和 actions。这使得大型应用程序中的状态管理更加模块化和可扩展。
通过使用 Vuex,开发人员可以更好地组织和管理应用程序的状态。它提供了一个集中式的数据流,让状态的变化变得可预测和可追踪,同时还提供了强大的工具和插件来帮助开发者调试和优化应用程序。
总结起来,Vuex 是一个用于 Vue.js 的状态管理库,通过集中管理和共享状态,简化了大型应用程序的状态管理和组件之间的通信。它的核心概念包括 State、Getters、Mutations、Actions 和 Modules,提供了一种可预测、可维护和可扩展的状态管理方案
2. 安装Vuex
注意版本问题:vuex3 - vue2、vuex4 - vue3
我这里使用的是vue2
bash
npm install vuex@3 --save
- vuex@3 指定要安装的 Vuex 版本是 3 版本。@3 是一个语法规则,用于指定特定的软件包版本。
- --save 是一个命令行选项,用于将安装的软件包添加到项目的 package.json 文件的 dependencies 部分。这样做可以记录项目使用的软件包及其版本,以便在其他环境中重新安装时保持一致。
3. 使用Vuex
3.1. 建一个index.js
src目录下建一个store目录,store目录底下建一个index.js
javascript
// 初始化一个vuex的实例
import Vuex from 'vuex'
import Vue from 'vue'
// 使用安装
Vue.use(Vuex)
// 初始化
const store = new Vuex.Store({
// 配置(state|mutations|actions)
})
export default store
3.2. 全局注入Store
即使在组件中不引入store也可以使用vuex
在main.js中注入
javascript
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
// 把store对象挂载到vue实例对象中,这样就可以在所有的组件中获取store中的数据了,
store,
components: { App },
template: '<App/>'
})
3.3. 创建一个store
javascript
const store = new Vuex.Store({
state: {
// 存放状态
user: {
name: 'curry',
age: 35
}
},
getters: {
// state的计算属性
},
mutations: {
// 更改state中状态的逻辑,同步操作
},
actions: {
// 提交mutation,异步操作
},
// 如果将store分成一个个的模块的话,则需要用到modules。
//然后在每一个module中写state, getters, mutations, actions等。
modules: {
a: moduleA,
b: moduleB,
// ...
}
});
主要有5个属性
- state -- 存放状态
- getters -- state的计算属性
- mutations -- 更改状态的逻辑,同步操作
- actions -- 提交mutation,异步操作
- mudules -- 将store模块化
3.4. 使用store
vue
<template>
<div>
<div class="hello">{{ $store.state.user.name }}</div>
</div>
</template>
<script>
export default {
}
</script>
3.5. 页面展示结果
4. state
State 是存储应用程序状态的对象。它是 Vuex store 的核心部分,包含了应用程序中的各种数据。
State 在 Vuex store 中充当单一数据源,即所有组件共享的数据中心。通过集中存储应用程序的状态,可以方便地管理和跟踪状态的变化,并确保状态的一致性。
state简单的说就是存放变量的地方,可以存字符串,对象、数组等
4.1. state使用示例
state中存放一个user对象
javascript
// 初始化一个vuex的实例
import Vuex from 'vuex'
import Vue from 'vue'
// 使用安装
Vue.use(Vuex)
// 初始化
const store = new Vuex.Store({
state: {
// 存放状态
user: {
name: 'curry',
age: 35
}
}
});
export default store
组件中展示store中的值
javascript
<template>
<div>
<div class="hello">{{ $store.state.user.name }}</div>
</div>
</template>
<script>
export default {
}
</script>
页面显示
4.2. mapState使用
mapState 是 Vuex 提供的一个辅助函数,用于简化在组件中访问 Vuex store 中的状态(state)。它可以帮助你将 Vuex store 中的状态映射到组件的计算属性中,使得在组件中使用状态更加方便。
vue
<template>
<div>
<div>{{ $store.state.user.name }}</div>
<div>{{ user.name }}</div>
<div>{{ userAlias.name }}</div>
<div>{{ age }}</div>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
data () {
return {
num: 10
}
},
computed: mapState({
// 箭头函数
user: state => state.user,
// 传字符串参数 'user' 等同于 `state => state.user`
userAlias: 'user',
// 为了能够使用 `this` 获取局部状态,必须使用常规函数
age (state) {
return state.user.age + this.num
}
})
}
</script>
4.3. ...mapState
在 Vuex 中,...mapState 是一种 JavaScript 扩展语法,用于在组件中快速绑定 Vuex store 中的状态到计算属性。
具体而言,... 表示解构语法(destructuring syntax),而 mapState 是 Vuex 提供的辅助函数。当我们使用 ...mapState 时,它会将 mapState 返回的对象展开,并将其中的属性和值分别添加到组件的计算属性中。
这种写法的好处在于它可以简化组件中的代码,避免了重复的代码和显式的属性赋值。通过使用 ...mapState,我们可以将 Vuex store 中的状态快速映射到组件的计算属性,使得在组件中访问和使用状态变得更加方便和简洁。
...mapState示例:
vue
<template>
<div>
<div>{{ user.name }}</div>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
data () {
return {
num: 10
}
},
computed: {
// 对象展开运算符:将此对象混入到外部对象中
...mapState(["user"])
}
}
</script>
在上面的示例中,我们使用 ...mapState 将 Vuex store 中的 user 状态映射到了组件的计算属性。这样在组件中我们可以直接使用 user,而不需要手动访问 this.$store.state.user
请注意,...mapState 仅仅是一种简写形式
你也可以选择使用完整的对象语法来手动映射状态到计算属性。
例如:
vue
<template>
<div>
<div>{{ user.name }}</div>
<div>{{ age }}</div>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
data () {
return {
num: 10
}
},
computed: {
// 对象展开运算符:将此对象混入到外部对象中
...mapState({
user: state => state.user,
age: state => state.user.age
})
}
}
</script>
5. Getters
Getters 是用于从 Vuex store 中获取派生状态的函数。它们类似于组件中的计算属性,但是可以在整个应用程序中共享和重用。
通过定义 Getters,可以对存储在 Vuex store 中的状态进行一些计算、筛选或转换,以生成新的派生状态。Getters 可以访问 store 的 state,并且可以接收其他 getters 作为参数。它们可以避免在多个组件中重复编写相同的计算逻辑。
5.1. getters使用示例
javascript
// // 初始化一个vuex的实例
import Vuex from 'vuex'
import Vue from 'vue'
// 使用安装
Vue.use(Vuex)
// 初始化
const store = new Vuex.Store({
state: {
// 存放状态
user: {
name: 'curry',
age: 35
}
},
getters: {
// 获取全名
fullName: state => {
return "史蒂芬" + state.user.name
},
userInfo: state => {
return state.user.name + "今年" + state.user.age + "岁"
}
}
});
export default store
vue
<template>
<div>
<div>全名:{{ $store.getters.fullName }}</div>
<div>今年多大了:{{ $store.getters.userInfo }}</div>
</div>
</template>
<script>
export default {
}
</script>
5.2. mapGetters
与mapStore用法一样的
vue
<template>
<div>
<div>全名:{{ fullName }}</div>
<div>今年多大了:{{ userInfo }}</div>
</div>
</template>
<script>
import {mapGetters} from 'vuex';
export default {
computed: {
...mapGetters(['fullName', 'userInfo'])
}
}
</script>
6. mutations
Mutations 是用于修改 Vuex store 中状态的方法。它们是 Vuex 中的同步操作,负责修改 store 的状态,并且每个 mutation 都有一个字符串类型的事件名和一个回调函数。
6.1. mutations使用示例
javascript
// // 初始化一个vuex的实例
import Vuex from 'vuex'
import Vue from 'vue'
// 使用安装
Vue.use(Vuex)
// 初始化
const store = new Vuex.Store({
state: {
// 存放状态
user: {
name: 'curry',
age: 35
}
},
mutations: {
// 更改state中状态的逻辑,同步操作
updateName(state) {
state.user.name = 'James'
},
updateAge(state) {
state.user.age = 39
},
resetUser(state) {
state.user = {
name: 'curry',
age: 35
}
}
},
});
export default store
在组件中使用这些 Mutations,你需要使用 commit 方法来触发它们
vue
<template>
<div>
<div>姓名:{{ $store.state.user.name }}</div>
<div>年龄:{{ $store.state.user.age }}</div>
<button @click="updateName">修改姓名</button>
<button @click="updateAge">修改年龄</button>
<button @click="resetUser">重置用户</button>
</div>
</template>
<script>
export default {
methods: {
updateName() {
this.$store.commit('updateName')
},
updateAge() {
this.$store.commit('updateAge')
},
resetUser() {
this.$store.commit('resetUser')
}
}
}
</script>
7. actions
Actions 是用于处理异步操作和触发 Mutations 的方法。Actions 允许在 Vuex store 中执行异步操作,如发起网络请求、访问 API 或执行其他异步任务。
Actions 类似于 Mutations,它们也有一个字符串类型的事件名和一个回调函数。
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态,而 Mutation是直接改变状态;
- Action 可以包含任意异步操作,Mutation 包含的必须是同步操作。
7.1. actions使用示例
javascript
// // 初始化一个vuex的实例
import Vuex from 'vuex'
import Vue from 'vue'
// 使用安装
Vue.use(Vuex)
// 初始化
const store = new Vuex.Store({
state: {
// 存放状态
user: {
name: 'curry',
age: 35
}
},
mutations: {
// 更改state中状态的逻辑,同步操作
updateName(state) {
state.user.name = 'James'
console.log(state.user.name)
},
updateAge(state) {
state.user.age = 39
},
resetUser(state) {
state.user = {
name: 'curry',
age: 35
}
}
},
actions: {
updateName(context) {
context.commit('updateName')
},
updateNameAsync(context) {
setTimeout(() => {
context.commit('updateName')
}, 2000)
}
}
});
export default store
该 Action 包含一个异步的updateNameAsync方法,点击后2秒钟返回结果
vue
<template>
<div>
<div>姓名:{{ $store.state.user.name }}</div>
<div>年龄:{{ $store.state.user.age }}</div>
<button @click="updateName">修改姓名</button>
<button @click="updateNameAsync">异步修改姓名</button>
</div>
</template>
<script>
export default {
methods: {
updateName() {
// 触发action(必须调用dispatch方法)
this.$store.dispatch('updateName')
},
updateNameAsync() {
// 触发action(必须调用dispatch方法)
this.$store.dispatch('updateNameAsync')
}
}
}
</script>