Vuex是一个专为Vue.js应用程序开发的状态管理模式和库。它允许你以集中化的方式管理应用程序的所有组件的状态,并提供了一种可预测的状态管理方案。
在Vue.js中,组件之间的数据传递通常通过props和事件来实现。然而,当应用程序变得复杂,组件之间的数据流可能变得混乱和难以维护。Vuex解决了这个问题,提供了一个集中的存储(store)来管理应用程序的状态。
Vuex的核心概念包括:
-
State(状态):应用程序的状态存储在单一状态树(Single State Tree)中,即store对象中的state。状态可以通过store.state访问。
-
Getters(获取器):用于从状态树中派生出一些衍生数据,类似于计算属性(computed)。Getters可以通过store.getters访问。
-
Mutations(变更):用于修改状态的唯一途径。Mutations是同步的操作,用于响应从组件中派发的动作(actions)。Mutations可以通过store.commit方法调用。
-
Actions(动作):用于处理异步操作和复杂的业务逻辑,可以包含多个Mutations的调用。Actions可以通过store.dispatch方法调用。
-
Modules(模块):用于将大型的store拆分成更小的模块,每个模块都有自己的state、getters、mutations和actions。
使用Vuex的好处包括:
- 集中化的状态管理:将应用程序的状态集中存储在一个地方,方便管理和维护。
- 可预测的状态变更:通过Mutations来修改状态,可以更好地跟踪状态的变化,便于调试和追踪。
- 共享状态:可以在多个组件之间共享状态,避免了通过props和事件传递数据的繁琐和复杂性。
- 更好的组织代码:通过模块化的方式来组织store,使得代码结构更清晰和可维护。
在Vue.js应用程序中使用Vuex需要先安装Vuex库,并在应用程序的入口文件中创建一个store实例,然后在组件中通过各种方式(如mapState、mapGetters、mapMutations和mapActions等辅助函数)来访问和操作状态。
在代码中使用Vuex,需要经过以下步骤:
- 安装Vuex:首先,在项目中安装Vuex库。
npm install vuex
pnpm install vuex
yarn install vuex
2.创建Store实例:一般来说我们会将store(index.js文件中创建Vuex的Store实例)进行一个模块化的划分,这个实例将包含应用程序的state、getters、mutations和actions。在应用程序的入口文件(通常是main.js
)中,将store挂载到vue上。
vuex中定义数据
import Vue from 'vue'
import Vuex from 'Vuex'
// 注册 Vuex 组件
Vue.use(Vuex)
// 创建一个Vuex 实例
const store = new Vuex.Store({
state () { // 数据
return {
count: 0,
list: []
}
},
mutations: { // 数据修改需要在mutations中处理
// 接受两个参数 state是定义数据,payload是荷载 修改时传入的数据
方法名 (state,payload) {
state.count = payload
},
changeList(state,payload) {
state.list = payload // 注意 list 中需要的值要根据接口返回的值给 这里不做演示 我们直接当做payload就是list需要的值了
}
},
actions: { // 处理异步请求
// 异步请求方法名 (context,payload) {
// 接受两个参数 context 上下文 用于将异步请求获取的数据通过commit调用mutations上面的方法修改数据 ,
// payload 荷载 简单来说就是发送请求传递的数据 假如我们发送axios请求 但是需要数据 而这个payload 就是数据来源}
getList( context,payload ) {
const res = axios('url',payload) // 注意 我们这里是没有接口和数据的 只是做个演示
// 假如我们获取到了数据 这个时候我们需要将数据给到list 需要通过mutations
context.commit('changeList',payload)
}
},
getters: {
// 相当于计算属性
myInfo(state) {
return `信息是${state.count}` // 注意这里我们使用了es6语法中的模板字字符串进行了拼接
}
}
})
export default store
main.js中挂载
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store' // 导入vuex模块
Vue.config.productionTip = false
new Vue({
router,
store, // 使用
render: h => h(App)
}).$mount('#app')
3. 通过vuex我们就能够实现数据共享,如下我们在页面中使用vuex中的数据(在这里我们重新定义数据并使用)
① 定义vuex中的数据
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
current: 0,
name: '小田',
age: 18
},
// 使用场景: 当我们获取数据想要对数据进一步做处理的时候,我们可以使用,例如下面代码中拼接
getters: {
getMyInfo (state) {
return `我的名字是${state.name},我的年龄是${state.age}岁`
}
},
mutations: {
changeCurrent (state, payload) {
state.current = payload
}
},
actions: {
},
modules: {
}
})
②在页面中使用数据 ( 下面代码中只是实现了数据的共享 )
<template>
<div>
<a href="#"
:class="{ action : current === 0 }" @click="changeCurrent(0)">选项1</a>
<a href="#"
:class="{ action : current === 1}" @click="changeCurrent(1)">选项2</a>
<a href="#"
:class="{ action : current === 2}" @click="changeCurrent(2)">选项3</a>
<a href="#"
:class="{ action : current === 3}" @click="changeCurrent(3)">选项4</a>
<div>我的信息: {{ info }}</div>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
export default {
name: 'TabStore',
data() {
return {
info: ''
}
}
computed: {
...mapState(['current']) // 辅助函数
},
mounted() {
// 这里获取getters中的数据
this.info = this.$store.getters.getMyInfo
},
methods: {
//...mapMutations(['changeCurrent']) // 辅助函数
// 如果我们不使用辅助函数去调用mutations中的方法,使用方法如下
changeCurrent(index) {
this.store.commit('方法名',index)
}
}
}
</script>
<style>
a {
padding-left: 10px;
font-size: 20px;
text-decoration: none;
}
.action {
color: red;
}
</style>
③ modules的使用, 就是将vuex中的数据进行一个模块化的划分,不同页面中的数据都存在以自己组件命名的vuex中,模块化的目的就是便于数据的管理与维护
modules使用场景:
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割
在模块中使用:namespaced: true, 命名空间,添加之后,当前模块下的标识符可以和其它模块相同,用于解决不同模块的命名冲突问题。
使用步骤
1 . 在store/index.js中 导入我们创建的模块
import Vue from 'vue'
import Vuex from 'vuex'
import count from './modules/count'
import users from './modules/users'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
namespaced: true, // 开启命名空间
count,
users
}
})
export default store
2.users.js中的代码
const user = {
namespaced: true, // 开启命名空间
state: {
user: {}
},
mutations: {
setUser (state, payload) {
state.user = payload
}
},
getters: {},
actions: {
setName (state, payload) {
return new Promise(resolve => {
setTimeout(function () {
state.user = payload
resolve(state.user)
}, 2000)
})
}
}
}
export default user
3. 在vue中使用
// commit 执行mutations里的方法,同步操作
// 注意 我们这里调用模块中的方法时的方法为 : '模块名'/方法
this.$store.commit('user/setUser', {name: '张三'});
console.log(this.user.name);
// dispatch 执行actions里的方法,异步操作
// 注意 我们这里调用模块中的方法时的方法为 : '模块名'/方法
this.$store.dispatch('user/setName', {name: '李四'}).then(res => {
console.log(res.name);
})