Vue全家桶系列四:Vuex 状态管理模式

591 阅读9分钟

Vuex 状态管理模式 - 官方文档

Ant Design of Vue 官方文档

阅读前先知:↓↓↓

我已将源代码上传到了我的码云仓库中,感兴趣的可以去下载源码,

点我 - 跳转到源码仓库地址, 下载源代码配合文章学习!

边看博文,边看源码,根据博客和源代码自己动手Demo敲一遍,这种最简单的方式让你快速掌握Vuex 状态管理,加油吧! 建议你用vue cli搭建项目时,不要使用eslint和typescript,会多出很多不必要的麻烦。

Vuex基础

vuex概述

// -------------------- vuex概述 -------------------
传统方式之间数据的共享, 效率不高,传值麻烦,不易于维护。 vuex数据共享,易于维护。提高开发效率。

父向子传值: v-bind,  子向父传值 v-on 事件绑定, 
兄弟之间的共享数据, EventBus. $on 接收数据的那个, $emit 发送数据的那个。

使用vuex的好处易于维护,高效实现数据之间的数据共享,
数据是响应式的,能保持数据与页面的同步。
一般只有共享的数据,才储存到vuex中, 私有的数据还是储存在组件自身的data中
vuex是一种全局数据管理的一种机制,可以实现组件之间的数据共享

vuex的基本使用

// -------------------- vuex的基本使用 -------------------
用ui面板可视化创建一个新的项目:照图片安装即可。
main中导入了store这个文件,并·挂载到vue对象身上。
store中导入了vuex,使用vuex.Store创建了数据共享对象,
并通过export default向外导出了对象。对象中包含了共享的数据data,
mutations用来封装同步方法操作数据,actions用来处理异步方法。

初始化计数器项目的基本结构

// -------------------- 初始化计数器项目的基本结构 -------------------
创建好项目后,开始初始化页面结构,将2个组件导入到Vue页面,
并在components中配置组件,在把组件挂载在自己的根元素里面去展示。
1-2:注意格式化工具用.prettierrc中修改格式化方式,semi关闭结尾;分号, 
singleQuote使用单引号。选择prettier格式化插件去格式化文件。
3-4:添加到本地仓库,页面最新的样式就是组件自己内容

定义并访问全局共享的数据

// -------------------- 定义并访问全局共享的数据 -------------------
完成了页面子组件在App根组件的挂载,开始在store.js中定义共享数据,在子组件中去渲染
1-2:在store.js中定义了count数据,
3-4:子组件通过$store.state.count吧数据展示到了自己的页面中

组件访问state中数据的第二种方式

// -------------------- 组件访问state中数据的第二种方式 -------------------
了解了方式1去把store下data中的数据渲染到子组件,方式2用映射方式,把数据映射到自己的页面中

1-2:在子组件的script中, 通过import { mapState } form 'vuex',从vuex组件身上解构出mapState专门获取state中的数据。

在export default 的computed
中
...mapState(['count'])将state中的count数据映射为自己,
所以就能直接使用{{count}}把数据渲染到自己template中

mutation的基本使用

// -------------------- mutation的基本使用 -------------------
知道了mapState方式把数据映射为自己的数据后,
开始完成用store中自己的mutations封装函数去操作自己state中的数据。
子组件通过this.$store.commit(调用封装的方法)实现修改共享的数据
1:方式1,是在子组件中直接操作了数据,这种方式是不合法的,
不允许子组件自己动手去修改store中的数据,
只能委托mutations封装函数去操作自己的数据

2:方式2:mutations封装函数,封装函数,参数1,
就是自己的state数据共享对象,函数中操作了数据
2.1:子组件中在点击事件函数中,
通过this.$store.commit('调用store中的封装的方法'),实现了数据的修改

触发mutation的时候携带参数

// -------------------- 触发mutation的时候携带参数 -------------------
使用了mutations操作了自己的数据,开始学会封装函数的参数2,携带参数去操作
1-2-3:参数2接收的是子组件调用函数,传递了参数1,通过它能实现+N的 操作

触发mutation的第二种方式

// -------------------- 触发mutation的第二种方式 -------------------
了解了mutation中的参数2,实现了数据+N,开始学会方式2,
mapMutations映射展开的方式去获取封装函数。实现页面数据的修改
1-2-3:从vuex中解构出了mapMutations方法,
在methods中...mapMutatiosn['封装函数的名称'],
在自己的事件函数中,调用了该封装函数,实现了数据的修改。

action的基本使用

// -------------------- action的基本使用 -------------------
学会了操作同步方法的操作,开始学会异步函数放在actions中去操作。
context就是vuex对象,context.commit就能拿到同步中的方法,
子组件通过this.$store.dispath拿到异步函数的方法。实现本页面的数据修改。
1:在mutations如果使用了异步方法,页面数值会发生改变,
但是数据实际没有发生改变,vuex是不允许在mutations中使用异步方法的
2:-3-4:异步方法必须写在actions中,
context其实就是vuex这个对象,通过它就能context.commit拿到同步中的函数封装,
实现了数据的修改
子组件必须通过this.$store.dispatch接收异步函数的分支,实现自己页面数据的修改

触发action的时候携带参数

// -------------------- 触发action的时候携带参数 -------------------
学会了异步方法的操作,开始学会异步方法接收参数,实现+n的操作
1-2-3:异步函的参数2就是子组件函数的参数2,
通过它能把数据传递给同步方法,实现自己数据的修改。
子组件中的函数传递了参数2,实现了本页面数据的修改

触发action的第二种方式

// -------------------- 触发action的第二种方式 -------------------
学会了异步函数的参数2,开始异步方式2,mapActions将方法映射为自己的方法,
在点击事件中直接把方法名字挂上,即可实现数据的修改
1-2-3: 在子组件中将mapActions从vuex中解构出来,
并在methods中...mapActions['异步函数'],
就可以在点击事件中,直接使用该方法。
因为已经被映射为自己的方法了。相当于用自己的方法了

getter的使用

// -------------------- getter的使用 -------------------
学会了方式2mapActions将异步函数映射为自己的方法,
开始学会getters数据加工方法,
把加工的数据通过mapGetters映射为自己的数据,在自己页面渲染
1-2-3-4-5:在getters中能够把数据加工封装给外部的组件享用,
子组件通过mapGetters解构出该方法,
在methods中...mapGetters['包装的方法名'],
实现包装的数据获取,把数据通过{{$store.getters.showNum}}
把包装的函数名渲染到页面中,实现了数据的二次加工

Vuex 画图总结:

阶段小结: 基于Vuex的todos任务列表案例

新建项目并初始化基本结构

// ------------------------- 新建项目并初始化基本结构 -----------------------
用ui可视化创建项目
用ui可视化创建项目,记得下载Vuex,其他按照图片,完成项目的初始化
初始化页面结构
完成了项目创建,开始用导师准备写好的代码,快速完成页面的布局
1-2-3-4-5:注意main中还没有导入store.js,并且eslint语法提示警告,
在.prettierrc中配置格式化规则,解决警告。
6:这个todo列表页面是导师提前准备好的,拷贝即可。
分为3大部分,template中遍历了数据,展示todo任务,data中返回了一个list数据, 
style中完成了页面基础的样式布局
7:页面效果:
A添加任务 
B切换任务状态  
C查看未完成  
D查看已完成  
E清除已完成  
F点击删除任务  

动态加载任务列表数据

// ------------------------- 动态加载任务列表数据 -----------------------
完成了页面的创建和布局渲染,开始完成数据的抽离,再使用axios把户数给请求渲染回表格中
1:导入store.js
2:抽离数据,只留下list空数组
3:在state中定义空数组,用来接收数据,
在mutations中封装函数接收数据,在actions发起异步数据的请求,把数据填充会空数组中。 
4:,通过解构出mapState, 在create中用this.$store.dispath触发异步函数,
去发起数据请求。在计算属性中computed展开list数据,把它映射为自己的数据,
直接给list中:dataSource=list接收数据取遍历渲染。
5:页面效果,页面数据正常没有发生改变

实现文本框与store数据的双向同步

// ------------------------- 实现文本框与store数据的双向同步 -----------------------
完成了数据渲染,开始完成把输入框中的值储存到store的数据中
1::value绑定store中的属性,@change输入时触发的事件函数,
通过...mapState,拿到inputValue映射为自己的数据,去渲染。handleInputChange拿到输入框的值,
并通过this.$store.commit触发store中的图标函数,
把输入框中只传递过去
2:mutations同步函数封装中,把获取到的数据,
直接赋值给了state中的inputValue,
实现了输入框中的数据,储存到公共数据中
3:页面效果,输入框中的数据,已经储存在store中了

完成添加事项的操作

// ------------------------- 完成添加事项的操作 -----------------------
完成了把输入框中的数据储存到store中了,开始完成添加功能

1:点击添加的时候,判断如果没哟UN诶人,就通过组件弹出提示信息,
反之有内容,就直接出发store中的同步函数,去帮忙添加任务。 
2:因为list.json中有4个数据了,所以state中的nextId是从5开始。
在函数封装中创建一个任务对象,有id和输入框的内容+done任务完成状态。
把这个对象添加到list数组中,让id++,
并清空输入框中的内容。完成了添加功能,页面会实时更新的

完成删除任务事项的操作

// ------------------------- 完成删除任务事项的操作 -----------------------
完成了添加任务的功能,开始完成点击删除的功能
1:点击事件中把id携带,在事件函数中通过this.$store.commit触发同步函数,把id给它。
2:同步函数中通过findIndex根据ID找到那条数据,
从数组中删除即可,页面数据实时更新了,实现了删除功能
3:点击删除一条任务

动态绑定复选框的选中状态

// ------------------------- 动态绑定复选框的选中状态 -----------------------
完成了删除任务的功能,开始完成,根据done的状态,渲染复选框的选中
1:list.json中done:true表示任务已完成
2::checked-item.done动态绑定done属性,
3:页面就实现了根据done渲染复选框的选中状态了

修改任务事项的完成状态

// ------------------------- 修改任务事项的完成状态 -----------------------
完成了任务复选框的状态渲染,开始完成复选框的状态修改
1:点击的时候把e事件对象和id给函数,
函数中创建params事件对象,调用store同步函数把param传递过去。
2:同步函数中参数2就是传递过来的param对象,
通过findIndex找到这个对象,判断如果!==-1表示对象存在,
就把对象中的done属性就和复选框的选中状态一致。
实现了数据中的done属性的修改
3:页面效果点击完成任务的已完成和未完成

使用getters统计未完成的任务条数

// ------------------------- 使用getters统计未完成的任务条数 -----------------------
1:在store的getters数据包装,用filter过滤出未完成数组的长度,
2:-3:通过解构mapGetters用展开映射unDoenlength为自己方法,
直接把该返回的返回值在插值表达式中渲染,完成了未完成任务的统计功能

清除已完成的任务

// ------------------------- 清除已完成的任务 -----------------------
完成了未完成任务的数量统计,开始完成清除已经完成的任务功能
1:点击清除触发函数,函数中调用了同步函数
2:同步函数中通过filter将未完成的返回,其实就是变相的把完成的数据给过滤掉了,实现了删除功能
3:页面效果,点击清除已完成,将已完成的删除掉了,剩下未完成的

动态切换按钮的高亮效果

// ------------------------- 动态切换按钮的高亮效果 -----------------------
完成了清除任务的功能,开始完成tab的高亮效果
1:点击的时候,触发的是同一个事件散户,
只是形参里面的字符串不一样而已,函数中触发了store中的同步函数,把key传递过去
2:state中设置了viewKey默认是第一个高亮,
在事件中把stateKey=key,就是把点击菜单高亮的字符串,
替换掉自己字符串,实现了高亮切换的功能
3:页面效果,点击能切换高亮了

实现列表数据的动态切换

// ------------------------- 实现列表数据的动态切换 -----------------------
完成了点击高亮的切换功能,开始完成点击切换任务视图的功能
1:页面中:dataSource动态绑定数据,就能切换显示数据
2:通过展开,拿到了getters中的封装函数返回的数据
3:getters在函数封装判断字符串,根据字符串过滤出对应的数据,实现了数据切换功能
4:页面效果,实现了点击切换tab数据的功能

下一篇:一文掌握 - 微信小程序基础(上半部分)