文章目录五个核心概念1. state2. Getters的使用3 Mutations3.1 基本使用3.2 响应规则3.3 常量类型3.4 同步函数4. Action4.1 使用Promise5 Moudle6 项目结构五个核心概念const store=new Vuex.Store({state:{},mu...
文章目录
- 五个核心概念
- 1. state
- 2. Getters的使用
- 3 Mutations
- 3.1 基本使用
- 3.2 响应规则
- 3.3 常量类型
- 3.4 同步函数
- 4. Action
- 4.1 使用Promise
- 5 Moudle
- 6 项目结构
五个核心概念
const store=new Vuex.Store({
state:{},
mutations:{},
actions:{},
getters:{},
modules:{}
})
? 以上为五个核心概念的内容,接下来我们一一介绍:
? 首先贴出一张图以备我们后面使用:
1. state
? 首先我们需要弄清楚的是state的功能,我们前面提到state是用来放置我们所有状态的属性。
? 在Vuex中提出了单一状态树的概念,也就是单一数据源的意思。意思就是我们全局只有一个store实例,也就是是我们只有一个管家的角色,这样一来统一了数据源,不会造成一些不必要的冲突。
单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。
? 我们可以看一下State的定义和使用
定义:
state:{
counter:0
},
使用(可以在模板中使用也可以在计算属性中使用):
<p>{{$store.state.counter}}</p>
2. Getters的使用
? 这里的getters实际上类似于我们组件中的计算属性,通常用于返回我们某个状态改变后的状态。
? 并且我们定义的getters函数可以包含一个state的参数,这个参数的含义就是我们的store下的state状态
? 我们下面可以模拟一个场景:有一组学生我们需要获取其大于20岁的人以及个数。
student状态:
student:[
{id:1,name:'a',age:12},
{id:2,name:'b',age:21},
{id:3,name:'c',age:34},
{id:4,name:'d',age:26},
]
getters:
getters:{
more20person(state){
return state.student.filter((s) => {
return s.age>20
})
}
},
? 其实除此之外我们还可以为其传参,比如我们现在想让年不是age,而是我们给定的值。那么我们就需要返回一个函数类型的返回值,给返回的函数设定参数。
moreageperson(state){
return function (tt) {
console.log(tt);
return state.student.filter((s) =>s.age>tt)
}
},
使用方法:
<p>{{$store.getters.moreageperson(10)}}</p>
3 Mutations
? 通过文中一开始贴的图我们看出Vuex的store中状态更新的唯一方式就是通过提交Mutation的方式来进行,因为我么这里需要DevTools进行追踪我们状态的更新情况。
因此我们可以知道Mutation常常用于操作变更状态数据。
3.1 基本使用
? 一个Mutation主要包括两部分的内容:
- 字符串的事件类型
- 一个回调函数,其中可以包含两个参数一个是state,另一个是我们自定义传入的参数。
这是一个Mutation的实例代码:
mutations:{
increment(state){
state.counter++
}
}
使用方法(在组件中直接通过store的commit方法调用):
this.$store.commit('increment')
? 接下来可以看看它的传参,参数称为Mutaions的载荷(payload).
? 参数的方式有两种,一种是直接进行传入,这种方式的缺点是只能传入一个参数
? 第二种是传入一个对象,这就实现了定义多个参数的功能。
3.2 响应规则
通过上面的一些代码我们会发现Vuex中的state数据是响应式的,因为他们在刚一定义时就被加入到Vue的响应式系统中了,因此当我们改变了状态数据之后,我们数据也可以做到响应式了。
但是我们还需要遵守一些规则:
- 在刚开始初始化时就将state中的属性定义好
- 如果后期想添加或者删除属性,不能通过es的基本语法
我们需要使用Vue.set的方式给其赋值,使用Vue.delete的方式给其删除属性。
我们可以看一下以下的例子:
原数据:
info:{name:'cc',age:13},
使用普通方式增加属性
updatastate(state){
state.info['address']='北京'
}
这时运行代码,我们发现在devTools中数据确实更新了,但是我们用在界面上的数据并没有更新。
当我们使用第二种方式时:
updatastate(state){
// state.info['address']='北京'
Vue.set(state.info,'address','北京')
}
这时我们发现数据和界面都更新了。
这说明我们使用Vue的set方法内部可以将我们增添的属性加入它的响应式系统中
3.3 常量类型
? 在mutation中, 我们定义了很多事件类型(也就是其中的方法名称),当我们的项目增大时, Vuex管理的状态越来越多, 需要更新状态的情况越来越多, 那么意味着Mutation中的方法越来越多.
? 方法过多, 使用者需要花费大量的经历去记住这些方法, 甚至是多个文件间来回切换, 查看方法名称, 甚至如果不是复制的时候, 可能还会出现写错的情况.
? 因此我们使用常量替代Mutation事件的类型(上文提到的type),我们可以将这些常量放在一个单独的文件中, 方便管理以及让整个app所有的事件类型一目了然.
具体做法:
- 创建一个专门终于储存常量type名的文件,并导出
- 使用es6函数命名方式导出进行使用
[常量](state,payload){
}
3.4 同步函数
? 通常情况下, Vuex要求我们Mutation中的方法必须是同步方法.
? 我们可以看上面的图,会发现Vuex主要将后端的异步操作都交给了Action处理,异步操作结束后再交给Mutation。最主要的是在Mutation这一环节有一个DevTools追踪记录环节。
? 因而如果我们在这里使用异步的耗时操作DecTools是追踪不到我们我们的记录的。
? 我们可以在Mutation中加一个异步操作测试以下DevTools会不会追踪到我们数据的改变。
就用我们上文的改变属性操作:
updatastate(state){
setTimeout(() => {
Vue.set(state.info,'address','北京')
}, 1000);
}
},
这时我们发现DevTools是没有这条属性增加的记录的。
因此我们得出结论:不要再Mutation中执行任何异步的操作。
4. Action
? 经过文上对Mutaion同步函数的介绍你是否对Action有一定的理解,对,就是Vuex为我们专门用于异步耗时操作的一个环节。之后再取将我们数据提交到Mutation。
? Action中的函数是可以有两个参数的,一个是context,一个是我们的payload,payload参数和Mutation的参数使用是一样的。
? 其中context是指上下文,代表了我们的store对象。
这里我们依然使用上文的实例来进行对增添属性的异步操作:
actions: {
undatadata(context) {
setTimeout(() => {
context.commit('updatastate')
}, 2000);
}
},
使用dispeach进行调用事件:
<button @click="$store.dispatch('undatadata')">updata</button>
这时我们发现再devtools监听到了数据的变化。
4.1 使用Promise
如果我们这里增加需求,当异步操作完成之后来提醒我们异步操作完成。
这里有两种方式来处理,一种是回调函数的形式,一种就是promise:
我们这里直接来看promise:
actions: {
undatadata(context) {
return new Promise((resolve, reject) => {
setTimeout(() => {
context.commit('updatastate');
resolve('改变成功')
}, 2000);
});
}
},
使用:
datachange(){
this.$store.dispatch('undatadata').then((result) => {
console.log(result);
}).catch((err) => {
});
}
这里我们使undatadata方法返回一个Promise对象,然后世界this.$store.dispatch(‘方法名’)就可以直接拿到它的返回值,我们就可以直接在这里进行操作。
5 Moudle
? Module是模块的意思, 为什么在Vuex中我们要使用模块呢? Vue使用单一状态树,那么也意味着很多状态都会交给Vuex来管理。当应用变得非常复杂时,store对象就有可能变得相当臃肿.
? 为了解决这个问题, Vuex允许我们将store分割成模块(Module), 而每个模块拥有自己的state、mutation、action、getters等
这时从官网直接copy下来的代码:
const moduleA = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
? 定义了两个模块AB,直接再store的moudles中进行注册
? 但是再使用时我们需要注意要直接再store.state.模块名.内容
中调用,并不是再moudles中,这时vuex将moudles里面的内容放入到store的state中了。
? 需要注意的是我们moudles中的Mutation也是和普通的调用方法一样直接从store中调用的,注意不要于其他地方的mutation重名。但是模块里面Mutation中的参数state是模快内部的状态数据。
? 同样,对于模块内部的 action,局部状态通过 context.state
暴露出来,根节点状态则为 context.rootState
,具体我们可以打印context的内容来根据我们需求进行变换。这里的context对应的是本模块下的内容,root层需要其他的方法调用
? 对于模块内部的 getter,根节点状态会作为第三个参数暴露出来:state, getters, rootState。
6 项目结构
再开发中我们的vuex内容一般不会写在一个js文件中,回具体的分成不同文件结构,这样让我们的代码更加清晰。
来自官网
├── index.html
├── main.js
├── api
│ └── ... # 抽取出API请求
├── components
│ ├── App.vue
│ └── ...
└── store
├── index.js # 我们组装模块并导出 store 的地方
├── actions.js # 根级别的 action
├── mutations.js # 根级别的 mutation
└── modules
├── cart.js # 购物车模块
└── products.js # 产品模块
本文标题为:Vuex的五个核心概念
基础教程推荐
- 使用ajax跨域调用springboot框架的api传输文件 2023-02-23
- JS滚动到顶部踩坑解决记录 2023-07-10
- uniapp开发微信小程序自定义顶部导航栏功能实例 2022-10-21
- 在实战中可能碰到的几种ajax请求方法详解 2023-02-01
- Ajax+smarty技术实现无刷新分页 2022-12-15
- HTML clearfix清除浮动讲解 2022-11-20
- Ajax发送和接收请求 2022-12-15
- 关于Ajax跨域问题及解决方案详析 2023-02-23
- Javascript Bootstrap的网格系统,导航栏和轮播详解 2023-08-11
- cocos creator游戏实现loading加载页面,游戏启动加载动画 2022-10-29