Vuex 状态管理
Vuex 是一种集中管理所有组件中数据的机制。它和Pinia一样都是解决使用 props 和 $emit 事件在组件之间传递数据时,当组件之间频繁传递,层级增加时管理数据就变得困难。Vue 的官方状态管理库已更改为Pinia,Pinia 具有与 Vue 几乎完全相同它还增强的很多API的功能。Vuex 虽然仍在维护中,但是它不会在添加的新功能了,Vuex 应用程序迁移到 Pinia它可能会是一个更好的选择。在这里我们还会讲解一下Vuex 的使用方法,以方便大家在迁移Vuex的时候更加方便。Vuex官网https://vuex.vuejs.org/
创建项目后,进入项目文件夹,执行npm install命令安装vuex
第一章 Vue3项目创建 1 Vue CLI 创建vue项目
第一章 Vue3项目创建 2 使用 Webpack 5 搭建 vue项目
第一章 Vue3项目创建 3 Vite 创建 vue项目
第二章 Vue3 基础语法指令
第三章 Vue Router路由器的使用
第四章 VUE常用 UI 库 1 ( element-plus,Ant ,naiveui,ArcoDesign)
第四章 VUE常用 UI 库 2 ( ailwind 后台框架)
第五章 Vue 组件应用 1( Props )
第五章 Vue 组件应用 2 ( Emit )
第五章 Vue 组件应用 3( Slots )
第五章 Vue 组件应用 4 ( provide 和 inject )
第五章 Vue 组件应用 5 (Vue 插件)
第六章 Pinia,Vuex与axios,VueUse 1(Pinia)
第六章 Pinia,Vuex与axios,VueUse 2(Vuex)
第六章 Pinia,Vuex与axios,VueUse 3(VueUse)
第六章 Pinia,Vuex与axios,VueUse 4(axios)
npm install vuex@next --save
安装完vuex后,可以通过查看package.json来查看安装的vuex版本。
"dependencies": {
"pinia": "^2.0.28",
"vue": "^3.2.45",
"vuex": "^4.0.2"
},
在创建main.js中创建一个vuex对象作为全局的数据管理器,将这个vuex对象app.use到Vue项目中。
import { createApp } from 'vue'
import App from './App.vue'
import { createStore } from "vuex";
//vuex中的数据保存环境
const store = createStore({
state: {
message: '我是你第条Vuex数据'
},
mutations: {
},
actions: {
},
modules: {
}
});
const app = createApp(App)
app.use(store)
app.mount('#app')
Vuex中的这三个属性state,Getters,Actions在Pinia中都有了解过,Mutations,Modules在后边会有所介绍。
1Vuex 使用
我们在App.vue中模板中使用** s t o r e . s t a t e . m e s s a g e ∗ ∗ 可以获得 V u e x 中保存的共享数据 m e s s a g e 值。项目中所有的其他组件都可以使用 store.state.message **可以获得Vuex中保存的共享数据message值。项目中所有的其他组件都可以使用 store.state.message∗∗可以获得Vuex中保存的共享数据message值。项目中所有的其他组件都可以使用store共享数据中的值。
<script setup>
import VuexIndex from "./components/VuexIndex.vue"
</script>
<template>
<div id="app">
<h1>学习与使用Vuex </h1>
<h4>{{ $store.state.message }}</h4>
</div>
<VuexIndex></VuexIndex>
</template>
在components文件夹中创建一个VuexIndex.vue组件,在组件中使用useStore 解构方法获得Vuex中的数据内容。
<script setup>
import { useStore } from 'vuex';
const store = useStore();
</script>
<template>
<h1>VuexIndex子组件</h1>
{{store}}
</template>
在浏览器上显示学习与“使用Vuex 的内容”和store对象中的内容,说明我们保存在Vuex中的共享数据生效了。
Vuex 共享和管理数据,因此可以从任何组件以相同的方式访问它
方法与对象 | 说明 | 使用方法 |
---|---|---|
createStore | 创建数据共享器 | import { createStore } from “vuex” |
useStore | 获得数据共享器 | import { useStore } from ‘vuex’ |
$store | 模板中获得数据共享对象 | $store.state.属性 |
2 Vuex 基础属性
Vuex 中主要是操作States,Actions、Mutations和getters属性的。
在项目中的store文件夹中下创建vuexIndex.js文件,我们将main.js文件中创建createStore部分的代码移植到vuexIndex.js文件中,在vuexIndex.js文件中来实现store数据共享器的功能。
import { createStore } from "vuex";
//vuex中的数据环境
export const store = createStore({
state: {
message: '我是你第一个Vuex数据'
},
mutations: {
},
actions: {
},
modules: {
}
});
修改main.js中的代码使用引入的方法引入store对象,使用vue组件use方法加入store数据共享器到整个项目环境中。
import { createApp } from 'vue'
import App from './App.vue'
import {store} from './stores/vuexIndex'
const app = createApp(App)
app.use(store)
app.mount('#app')
1 state值设置
现在让我们使用 Vuex来 装入一个用户列表集合,在 store\vuexIndex.js 文件中store对象中的state加入用户列表信息。
import { createStore } from "vuex";
//vuex中的数据环境
export const store = createStore({
state: {
message: '我是你第一个Vuex数据',
users:[
{name: 'zhtbs', dept:'部门一', post:"经理",id:1},
{name: 'kimy', dept: '部门一',post:"工人",id:2},
{name: 'linda', dept: '部门二',post:"工人",id:3}
]
}
});
在子组件中VuexIndex.vue中使用store.state属性将它内面的users集合绑定都模板中v-for指令,将用户内容循环遍历出来。
<script setup>
import { useStore } from 'vuex';
const store = useStore();
</script>
<template>
<h1>VuexIndex子组件</h1>
<ul>
<li v-for="user in store.state.users">
名称:{{ user.name }}
部门:{{ user.dept }}
职务:{{ user.post }}
</li>
</ul>
</template>
2 getters设置
import { createStore } from "vuex";
//vuex中的数据环境
export const store = createStore({
......
getters: {
//统计
Countusers : function(state){
return state.users.length;
}
}
});
<script setup>
import { useStore } from 'vuex';
const store = useStore();
// 获得用户列表数量
let count=store.getters.Countusers;
</script>
<template>
<h1>VuexIndex子组件</h1>
<ul>
<li v-for="user in store.state.users">
名称:{{ user.name }}
部门:{{ user.dept }}
职务:{{ user.post }}
</li>
</ul>
<h3>列表数量:{{count}}</h3>
</template>
它只能在被描述为计算属性的组件中使用。如果你想在其他组件中做同样的处理,你需要为每个组件编写相同的代码。但是,如果您使用 Getters,它们将存储在 Vuex 存储中,因此您可以以相同的方式从其他组件使用它们。
3 mutations动作
Vuex 中的mutations属性中是定义修改state 值的方法。在Vue 组件中引入store对象,通过执行store对象中mutations方法来修改store对象中state的值。
mutations 方法默认第一参数是state
mutations: {
increment : function(state) {
}
}
修改vuexIndex.js代码在store对象中的mutations属性下创建方法increment,在这个方法中使用方法参数state,这个参数state就是整个store中的state,将state中count值进行累加。
import { createStore } from "vuex";
//vuex中的数据环境
export const store = createStore({
state: {
count: 0,
},
//更新动作
mutations: {
increment : function(state) {
state.count++
}
},
actions: {
}
});
Vuex 存储状态的改变方法是定义在mutations属性中动作,在组件中useStore对象使用commit函数触发mutations动作事件。大家都能理解state中的数据更新都是通过mutations属性中的动作来完成的。
在App.vue中代码中按钮中绑定increment事件,在increment事件中使用commit方法执行store中的increment方法,increment方法功能是store对象state值count累计加1。
<script setup>
import VuexIndex from './components/VuexIndex.vue'
import { useStore } from 'vuex';
const store = useStore();
const increment=()=>{
store.commit('increment')
}
</script>
<template>
<h1>学习与使用Vuex </h1>
<button v-on:click="increment">count 累计+1</button>
<h1>Count:{{ this.$store.state.count }}</h1>
</template>
在浏览中看到的结果是。
4 Actions 更新
Vuex 也提供别外一种用于更新状态值的函数 Actions。Actions与 mutations 功能一样都是用于更新状态state中的值,但有这两个属性也是有所区别的。
- Actions是通过mutations 来更新state中的值, 而不是自己直接改变state中状态。
- Actions操作可以包括异步处理功能。
在VuexIndex.js文件中创建actions属性,在actions属性中写入actionszht方法,在actionszht方法完成执行计算器累加功能。
actionszht方法中会传入一个context参数,context参数是Store对象中的全局环境,使用这个context全局环境的commit方法将mutations属性中的increment方法加入进来。
actionszht方法就可以使用mutations中的increment方法进行计数器累加功能了。
import { createStore } from "vuex";
//vuex中的数据环境
export const store = createStore({
state: {
count: 0,
},
mutations: {
increment : function(state) {
state.count++
}
},
actions: {
actionszht: function(context){
context.commit('increment')
}
}
});
让我们在 App.vue 中加入这个的 actionszht 方法,进行计数器累加工作。Commit 用于执行 mutation,而 dispatch 方法用于执行 action。
<script setup>
import { useStore } from 'vuex';
const store = useStore();
const increment=()=>{
store.dispatch('actionszht')
}
</script>
<template>
<button v-on:click="increment">count增加1</button>
<h1>Count:{{ this.$store.state.count }}</h1>
</template>
除了 state 和 commit 之外,context 还可以使用 dispatch 和 getters 方法。
Actions异步处理
异步处理常用于使用axios从服务器获取数据等情况。如果使用setTimeout函数获取图像进行异步处理,处理过程如下。3 秒后,突变增量被执行,计数增加 1。
actions: {
incrementOne: function(context){
setTimeout(() => {
context.commit('increment')
}, 3000)
}
}
通过到目前为止的解释,我们已经解释了下图中所有的Actions、Mutations和States。如果你能看懂下图,我想你差不多能理解 Vuex 的概念了。
为了检查您的理解,让我们根据文档中经常出现的计数示例,按照下图中的流程进行操作。
##3 Vuex 模块化
至此,Vuex 中存储的状态、突变、动作和 getter 都存储在 store\index.js 文件中。如果你的应用很小,你可以只用 index.js 文件来管理 Vuex 状态,但是随着应用的增长,代码量会越来越大,变得难以管理。
Vuex 允许模块化。模块化允许您根据文件的功能分离文件。例如,如果您的应用程序具有用户身份验证功能,请创建一个名为 user.js 的单独文件。为每个函数分离文件使代码管理更容易。
在 store 文件夹下创建一个 modules 文件夹,并创建一个 user.js 文件。
export const user = {
namespaced: true,
state: {
user: null,
},
mutations: {
setUser(state, payload) {
state.user = payload;
},
},
actions: {
login({ commit }) {
//登录业务
},
goout({ commit }) {
//退出业务
},
},
getters:{
},
};
创建的用户模块可以在 store\index.js 文件中设置,如下所示。
import { createStore } from "vuex";
import user from "./user";
//vuex中的数据环境
export const store = createStore({
modules: {
//导入模板到主模块中
user,
},
state: {
},
getters: {
},
mutations: {
},
actions: {
}
});
访问时为$store.state.user.user。此外,如果您想通过调度执行登录处理,它将是 dispatch(‘user/login’)。由于设置了 namespaced: true ,它变成了 user/login 而不是 login,并且可以使用命名空间设置操作。如果未设置 namespaced,它将是 dispatch(‘login’)。