Vuex状态管理
- 附:eslin中定义了不使用会报错
- 认识应用状态管理
- 什么是状态管理
- 旧模式下的状态管理
- Vuex的基本使用
- 安装Vuex
- 单一状态树
- State
- 使用vuex的方式(Vue3)
- mapState辅助函数(Vue2)
- Mutations
- mutations的使用和携带参数(Vue2)
- mutations使用常量定义名的写法(Vue2)
- mutations的使用(Vue3)
- Actions
- actions的使用(Vue2)
- 页面使用
- 页面使用有点繁琐,提供辅助函数 (Vue2)
- actions的使用映射(Vue3)
- actions的默认使用方法Vue3)
- actions的异步调用(Vue3)
- Getters
- 页面getters数据使用(Vue2)
- Modules
- 步骤一,建立子模块
- 步骤二,主模块中导入子模块
- 步骤三,页面中使用state中数据的时候,要加上子模块一层
- 步骤四,页面中使用getters中数据的时候,不需要加上子模块一层,直接用
- 子模块命名空间
- 设置命名空间为true后,页面调用方式变化
- module也可以修改或派发根组件哦!
附:eslin中定义了不使用会报错
- 很不方便,去关闭它
认识应用状态管理
什么是状态管理
- 开发中,需要进行各种各样的数据处理。这些数据需要保存再我们应用中的某一个位置,对于他们的管理就是状态管理
旧模式下的状态管理
- vue中的采用组件化的开发方式
- 而在组件中我们定义data或者在setup中返回使用的数据。这些数据称之为state
- 而在模板template中可以使用这些数据,模板被渲染为DOM,我们称为View
- 在模块中产生的行为动作,处理这写行为事件的时候,有可能会修改state,这个行为事件称之为actions
Vuex的基本使用
- 当对复杂的数据的状态管理的时候,会越来越庞大
- 当程序复杂时候。本身的state之间也会互相影响,会变得难以控制
- 解决方法:
- 考虑将组件的内部状态抽离出来,以一个全局单例的方式来管理
- 在这种模式下,组件树内构成一个巨大的视图View
- 不管在树的哪个位置,任何组件都能随时获取状态或者触发行为
- 通过定义和隔离状态管理各个概念,并且通过强制性的规则来维护视图和状态间的独立性
安装Vuex
npm install vuex
单一状态树
- Vuex采用单一状态树
- 用一个对象就包含了全部的应用层级的状态
- 采用的是SSOT,也就是单一数据源,也就是只有一个store
- 优势,单一状态树能够让我们最直接的方式找到某个状态的片段
State
- 一般新建store文件夹,,创建index.js文件·
- main.js导入挂载
使用vuex的方式(Vue3)
-
可以改数据,官方不建议直接修改state,必须通过提交Mutations
-
Mutations修改state修改
mapState辅助函数(Vue2)
- Vue2中的计算属性的映射状态
- 通过mapState辅助函数
Mutations
- 重要原则:mutations必须是同步函数
- 这是因为devtool工具会记录mutation的日记
- 每一条mutation被记录,devtools都需要捕捉到前一状态和后一状态的快照
- 但是在mutation中执行异步操作,就无法追踪到数据变化
- vue2中
- 通过commit方法
mutations的使用和携带参数(Vue2)
- vue2中
- 对象风格的提交方式
mutations使用常量定义名的写法(Vue2)
- 步骤一:新建一个集中管理常量的地方,并导出
- 步骤二:vuex中导入并定义对应的方法
- 步骤三,页面使用
mutations的使用(Vue3)
<template>
<div class="app">
<h3>当前vuex的值:{{ $store.state.num }}</h3>
<h3>当前vuex的值:{{ $store.state.num1 }}</h3>
<button @click="setnum">修改vuex值</button>
<button @click="getnum">mutations修改vuex值</button>
</div>
</template>
<script setup>
import { useStore } from "vuex";
const store = useStore();
function setnum(){
store.commit('setrenum')
}
function getnum(){
store.commit('Textnum',{name:"乞力马扎罗"})
}
</script>
Actions
actions的使用(Vue2)
- actions提交的是mutation,而不是直接变更状态
- actions可以包含任意异步操作
- (参数context)
- context是一个和store实例具有相同的方法和属性的context对象
- 故。可以从其中获取到commit方法来提交mutation
- 也。可以通过context.state和context.getters来获取state和getters
- 修改对象
页面使用
- vue2中,获取
getnum() {
this.$store.dispatch("getnumAct");
},
- 修改对象
setnum() {
let obj ={
name:"乞力马扎罗",
type:1,
}
this.$store.dispatch("setnumAct",obj);
},
页面使用有点繁琐,提供辅助函数 (Vue2)
actions的使用映射(Vue3)
<template>
<div class="app">
<h3>当前vuex的值:{{ $store.state.num }}</h3>
<h3>当前vuex的值:{{ $store.state.num1 }}</h3>
<button @click="setnumAct({ name: 'qqq' })">修改vuex值</button>
<button @click="getnumAct">Actions修改vuex值</button>
</div>
</template>
<script setup>
import { mapActions, useStore } from "vuex";
const store = useStore();
// const { getnumAct, setnumAct } = mapActions(["setnumAct", "getnumAct"]);
// 直接使用是使用不了的,因为这个方法里面本身是this.$store这样的方式的,setup里面不支持
// 解决方法
// 循环,通过bind,将store绑定在store身上
const actions = mapActions(["setnumAct", "getnumAct"]);
const newobject = {};
Object.keys(actions).forEach(key => {
newobject[key] = actions[key].bind({ $store: store });
});
const { getnumAct, setnumAct } = newobject;
</script>
actions的默认使用方法Vue3)
<template>
<div class="app">
<h3>当前vuex的值:{{ $store.state.num }}</h3>
<h3>当前vuex的值:{{ $store.state.num1 }}</h3>
<button @click="setnum">修改vuex值</button>
<button @click="getnumAct">Actions修改vuex值</button>
</div>
</template>
<script setup>
import { mapActions, useStore } from "vuex";
const store = useStore();
//
function setnum() {
store.dispatch("setnumAct", { name: "qqq" });
}
//
function getnum() {
store.dispatch("getnumAct");
}
</script>
actions的异步调用(Vue3)
- 目的知道action是什么时候结束的
actions: {
getnumAct(context) {
return new Promise((resolve, reject) => {
resolve()
})
}
}
Getters
- 某些属性我们可能需要经过变化后来使用,这个时候需要getters
- 参数一,state获得state定义的数据
- 参数二,代表其他getters,可以调用getters中的其他getters
页面getters数据使用(Vue2)
- Vue2中
- 方式一:页面直接调用
- 方式二:通过mapGetters辅助函数调用
- vue3中的setup中 通过toRefs (Vue3)
<script setup>
import { toRefs } from "vue";
import { useStore } from "vuex";
const store = useStore();
const {addnum} =toRefs(store.getters)
</script>
- 方式二:通过computed属性(Vue3)
<script setup>
import { computed } from "vue";
import { useStore } from "vuex";
const store = useStore();
const {addnum} =computed(()=>store.getters.num)
</script>
Modules
- 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象,当应用变得非常复杂的时候,store对象会变得非常复杂
- 为了解决上面问题,Vuex允许我们将store分割成模块(modules)
- 每个模块拥有自己的state,mutation,action,getter,甚至是嵌套子模块
步骤一,建立子模块
- 可以新建一个专门存放子模块的地方
步骤二,主模块中导入子模块
步骤三,页面中使用state中数据的时候,要加上子模块一层
步骤四,页面中使用getters中数据的时候,不需要加上子模块一层,直接用
<h3>当前vuex的值:{{ $store.state.home.num1 }}</h3>
<h3>当前vuex的getters值:{{ $store.getters.addnum }}</h3>
子模块命名空间
- 注意,子模块中的mutation和getters和actions最终会合并在主模块中,命名不可和其他模块重复
- 也就是说,默认情况下。模块内部的action和mutation和getters仍然是注册在全局的命名空间中的
- 这样使多个模块能够对同一个action或mutation或getters作出响应
- 如果我们希望模块具有更高的封装性和复用性,可以添加namespaced:true的方式使其成为带命名空间的模块