Vuex 入门指南
1.Vuex是什么?
我们还是像以往一样先看一看官方文档对此的解读(Vuex 是什么? · GitBook)
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。
是不是又遇到了很多看起来很高大上听起来却一脸懵逼的专业术语?别急别急,我们慢慢来剖析一下这个Vuex究竟是个啥东西,他能做些啥。
2.Vuex到底用来做什么?
用通俗一点的话来说,Vuex就是一个用于管理SPA项目(不知道SPA是什么?请参考本专栏代码之美 - 知乎专栏中的历史文章)中状态的开源产品。
接下来又引出了一个问题,什么是状态,为什么要用Vuex这个东西去管理它?
3.什么是状态?为什么要去管理它?
状态这个东西其实我们生活中随处可见。我们头顶上的灯就有两种状态,一种是开,一种是关。状态说白了就是灯这个对象的的某个属性的值。
如果你对状态和属性这两个概念还是有所不了解,那么我打一个其他的比方吧。
我们平时是否有玩过王者荣耀或者英雄联盟LOL之类的网游?这些游戏里面每一个英雄当前都有生命值,法力值,攻击力,法术强度,护甲和魔抗等等,这些是这个英雄的属性,也就是英雄这个对象当前的状态。
属性分为固定属性和可变属性,一般像LOL里面大部分ADC英雄如果没有特殊的被动或者其他装备的支持,那么它的的攻击距离都是固定的,这个就是固定属性,这种固定属性的状态由于正常情况下都是不变的,所以我们可以直接写死在代码中(这种写死在代码中的变量的值称为硬编码),但是像其他的攻击力法术强度等等都是随装备和等级变化,那么这种属性是可变属性。
这些属性的状态由于会根据用户的各种操作(比如说出装备,打怪升级升级)变化。在传统的Vue.js的组件化开发中,一般这些状态都是分散在各个组件中,此时此刻如果两个英雄互相打起来了,那么就得分别去不同的组件中取状态值,然后进行状态值的修改,最后还要互相读取对方的状态值。如果他们本身是父子组件,那么还可以通过事件触发或者Prop属性来传递状态,但是如果是不同的组件,由于由于Vue.js本身组件之间有作用域,它们无法直接相互通信,所以就需要一些东西例如Vuex去集中管理和追踪它的变化。(如果你现在还是不明白这一大段话,可以好好回顾一下官方文档中组件 - vue.js非父子组件通信 这个部分的内容)
在游戏中,这些状态一般以变量的形式保存在内存中,但是由于用户玩游戏的时候并不是直接去使用内存管理工具查看他们在内存里面的值,而是通过游戏界面去看这些值,所以还需要像Vue.js这种MVVM框架将状态同步到视图中。这就是Vue.js和Vuex之间的关系了。
4.什么情况下我应该使用 Vuex?
官方文档(Vuex 是什么? · GitBook)中说:
虽然 Vuex 可以帮助我们管理共享状态,但也附带了更多的概念和框架。这需要对短期和长期效益进行权衡。
如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的 global event bus 就足够您所需了。但是,如果您需要构建是一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。引用 Redux 的作者 Dan Abramov 的话说就是:
Flux 架构就像眼镜:您自会知道什么时候需要它。
他的意思其实就是如果开发的程序并不是很庞大,一个页面中的组件不是很多并且他们之间并不需要大量频繁的互相读写操作,那么就可以直接使用传统的Vue.js中的组件Prop或者事件触发来修改状态,或者用组件 - vue.js#非父子组件通信 中介绍的new一个空的Vue对象实例,并且通过事件触发等方式来跨组件通信。
否则的话还是建议使用Vuex。虽然Vuex本身需要有一段时间的学习成本,但是这个学习成本相对于你开发时期使用传统非父子组件通信机制遇到的各种坑来说还是比较划算的。这个就看你自己的权衡了。
5.Vuex怎么安装和使用?
在前面讲解Vue.js入门的时候,我们用的是Vue-Cli这个脚手架工具来搭建的,由于这个脚手架工具本身会帮我们配置好npm的package.json文件,这个文件里面包含了这个Vue.js项目中所有依赖的包。
但是默认情况下这个脚手架工具没有为我们将Vuex这个依赖包给包含进去,所以我们得自己去“声明”一下我们这个Vue.js项目中需要依赖Vuex这个包。
我们该怎么“声明”呢?现在有两种办法:
一种是直接修改package.json,这种方法看起来有点复杂,很多新手怕一不小心修改出错,可能会导致整个package.json文件结构出错,影响以后项目的依赖安装。
还有一种方法比较安全,只需要一行命令:
npm install vuex --save
表示安装vuex这个包,--save表示将这个依赖包与本项目的依赖关系写入package.json中。
然后我们仅仅安装了这个依赖包是没有用的,我们还得在之前Vue-Cli为我们自动构建好的项目文件中的main.js主入口文件的开头里面加上两行这样的代码:
import Vuex from 'vuex'
Vue.use(Vuex)
第一行是用ECMAScript6的import将vuex包导入进来(这个是不是和java中导入jar包以及php中导入命名空间很相似?)
第二行是Vue.js本身的插件注入语法(参考官方文档插件 - vue.js),将插件注入Vue.js的目的是方便我们在插件内部调用它。
6.官方文档的五大核心概念是什么?
打开官方文档(Introduction · GitBook)能看到五大核心概念,他们都是啥?看了半天官方文档我还是对它们没什么了解,楼主能不能以通俗易懂的方式讲解一下它们的作用?当然可以啦!
首先先看一遍这个代码,不需要你看懂它。
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
7.State(状态)
官方文档:State · GitBook
这个状态就是前面所介绍的“状态”值的存放处。
看第6节末尾的代码中,状态就是在state属性中以键值对的形式声明这个SPA中所有的状态。上面的代码中声明了一个count状态。
之所以要在这里声明所有状态的原因,一是让代码更加优雅,如果你接手你同事的项目的时候,能够一眼从Vuex的状态声明中看出这个应用中有哪些状态,肯定开发效率杠杠滴。二是如果在这里声明了状态,那么Vuex就能够追踪到这个状态的变化。那么Vue.js中就可以在视图中对这个状态做出响应。
读取状态当然也是直接读取这个属性里面的各种子属性了。
8.Getter(获取器)
官方文档:Getters · GitBook
这个获取器和一些后端开发中模型层ORM中的获取器其实是差不多的功能。
比如说后端返回给我们的是一个int类型的时间戳,我们想把这个时间戳转换成正常人类可读的文本型时间表现形式(比如说2017年3月11日 12:43:31),那么我们就得在所有获取该状态的代码中增加一个转换函数。
可是现在有了状态获取器之后,我们可以统一将这个时间戳转字符串的函数写在获取器里面,要调用的时候就直接调用获取器就好了。
还有一些其他场景也可以使用获取器,比如说像错误码这种东西一般都是一个数字码对应一个文字形式的错误原因,我们也可以通过获取器来实现通过错误码拉取错误原因的功能。
使用获取器的方法则是直接调用Vuex实例的getter下的各种函数即可。
9.Mutations(转变)
官方文档:Mutations · GitBook
这个Mutations其实国内目前也没有比较好的翻译,通常我们都是直接称Mutations。
我们前面只讲了可以通过调用Vuex的实例的state属性或者getter获取器来读取状态。但是没讲到如何修改状态。
官方文档中已经讲了需要先在Vuex实例的Mutations下编写对应的修改函数来修改状态。并且要修改的时候,要通过Vuex实例的commit方法来提交修改。也就是说任何对state状态的修改操作都必须写在Mutations中,并且还得用Vuex实例的commit来提交修改操作,并且由于Mutations函数可以传入参数,所以commit同理也可以传入参数。
这个时候可能有一些同学就会提问了,前面既然讲到了读取可以直接访问Vuex实例的state属性,为什么修改却不能直接去操作Vuex实例的state呢?官方文档和其他高手的回答是:
再次强调,我们通过提交 mutation 的方式,而非直接改变 store.state.count,是因为我们想要更明确地追踪到状态的变化。这个简单的约定能够让你的意图更加明显,这样你在阅读代码的时候能更容易地解读应用内部的状态改变。此外,这样也让我们有机会去实现一些能记录每次状态改变,保存状态快照的调试工具。有了它,我们甚至可以实现如时间穿梭般的调试体验。
相当于我们通过一个Mutations函数可以显式的在代码中告诉开发者,我们这个SPA中究竟会对状态进行哪些操作,操作方式是什么。并且在后期我们使用一些辅助开发工具,可以保存状态的快照,就像git或者svn一样可以回滚状态。如果你还是有点不明白,总之你就按照官方文档说的去做吧,等开发一段时间之后会慢慢明白作者的良苦用心的,哈哈。
还有一个问题就是为什么状态修改的提交必须通过Vuex实例的commit方法提交呢?为什么不能直接调用Mutations函数呢?除了上面官方文档中提到的原因,网上还有高手解释了:因为Vue.js的状态修改其实是在内部有一个修改队列,通过commit的方式提交修改可以保证状态的修改是有序的。
10.Actions(动作)
官方文档:Actions · GitBook
前面提到了Mutations中可以对状态进行操作,但是忘记告诉各位同学,Mutations中对状态的操作只能是同步操作,不能是异步操作。
如果这个时候我们有一个对状态的修改操作是异步的怎么办呢?
首先看看什么是异步操作?比如说ajax就可以选择是否发起异步请求,发起异步请求之后,我们就需要在回调函数里面进行请求结果的处理。关于JavaScript异步的知识大家可以先使用各种搜索引擎自学一下。
现在回到actions上来,看看官方文档(Actions · GitBook):
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
其实异步的状态修改本质上还是通过几个同步操作组合的,所以我们还是得先声明好mutation同步操作方法,然后在actions中进行异步操作。如果我们暂时手头上没有ajax接口用于异步请求,那么我们可以像官方文档一样用setTimeout这种最简单的测试方法来理解。
actions: {
incrementAsync ({ commit }) {
setTimeout(() => {
commit('increment')
}, 1000)
}
}
前面讲到了mutation是用commit来提交操作的,那么actions是怎么提交的呢?官方文档中说了actions是使用Vuex实例的dispatch方法来提交(其实说分发会更加准确)的。
至于其他更详细的actions操作官方文档讲的还是比较清楚的,没有什么比较复杂的概念,可以参考官方文档学习,这里不做更多讲解。
至于后面“组合actions”中提到的Promise对象以及 async / await 都是JavaScript中的一些特性,大家可以利用搜索引擎进行更多了解。
11.Modules(模块)
官方文档:Modules · GitBook
如果你的SPA项目非常的庞大,那么状态可能本身还需要进行分模块分类管理,这个时候就需要用到模块了。官方文档中已经给出了比较详细的模块操作代码,这里不再做更多讲解。
至于前面在将actions的时候,官方文档中说actions方法在声明的时候需要带上一个context参数,原因在这里可以得到解答:
对于模块内部的 action,context.state 是局部状态,根节点的状态是 context.rootState
12.严格模式
官方文档:严格模式 · GitBook
在严格模式下,无论何时发生了状态变更且不是由 mutation 函数引起的,将会抛出错误。这能保证所有的状态变更都能被调试工具跟踪到。
前面提到了state的修改需要通过提交Mutations或者分发Actions,但是事实上我直接修改state可以吗?当然也是可以的,但是在开发阶段,为了尽可能防止开发者直接修改,就可以通过严格模式来检测这种错误的修改方式,并且抛出异常。
但是官方文档后面也提到了:
不要在发布环境下启用严格模式!严格模式会深度监测状态树来检测不合规的状态变更——请确保在发布环境下关闭严格模式,以避免性能损失。
因此不要在生产环境下开启严格模式导致性能损失。
结语:
Vuex综合来看是一个非常适合在Vue.js中使用的状态管理工具,当然类似的状态管理工具也有很多,比如说React的Redux。
但是我们为了能够尽可能保证项目稳定性以及学习曲线的平滑,推荐在Vue.js中使用Vuex
Vuex 入门指南的更多相关文章
- Web API 入门指南 - 闲话安全
Web API入门指南有些朋友回复问了些安全方面的问题,安全方面可以写的东西实在太多了,这里尽量围绕着Web API的安全性来展开,介绍一些安全的基本概念,常见安全隐患.相关的防御技巧以及Web AP ...
- Vue.js 入门指南之“前传”(含sublime text 3 配置)
题记:关注Vue.js 很久了,但就是没有动手写过一行代码,今天准备入手,却发现自己比菜鸟还菜,于是四方寻找大牛指点,才终于找到了入门的“入门”,就算是“入门指南”的“前传”吧.此文献给跟我一样“白痴 ...
- yii2实战教程之新手入门指南-简单博客管理系统
作者:白狼 出处:http://www.manks.top/document/easy_blog_manage_system.html 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文 ...
- 【翻译】Fluent NHibernate介绍和入门指南
英文原文地址:https://github.com/jagregory/fluent-nhibernate/wiki/Getting-started 翻译原文地址:http://www.cnblogs ...
- ASP.NET MVC 5 入门指南汇总
经过前一段时间的翻译和编辑,我们陆续发出12篇ASP.NET MVC 5的入门文章.其中大部分翻译自ASP.NET MVC 5 官方教程,由于本系列文章言简意赅,篇幅适中,从一个web网站示例开始讲解 ...
- 一起学微软Power BI系列-官方文档-入门指南(1)Power BI初步介绍
我们在前一篇文章微软新神器-Power BI,一个简单易用,还用得起的BI产品中,我们初步介绍了Power BI的基本知识.由于Power BI是去年开始微软新发布的一个产品,虽然已经可以企业级应用, ...
- 一起学微软Power BI系列-官方文档-入门指南(2)获取源数据
我们在文章: 一起学微软Power BI系列-官方文档-入门指南(1)Power BI初步介绍中,我们介绍了官方入门文档的第一章.今天继续给大家介绍官方文档中,如何获取数据源的相关内容.虽然是英文,但 ...
- 一起学微软Power BI系列-官方文档-入门指南(3)Power BI建模
我们前2篇文章:一起学微软Power BI系列-官方文档-入门指南(1)Power BI初步介绍 和一起学微软Power BI系列-官方文档-入门指南(2)获取源数据 中,我们介绍了官方入门文档与获取 ...
- 一起学微软Power BI系列-官方文档-入门指南(4)Power BI的可视化
在前面的系列文章中,我们介绍了官方有关获取数据,以及建模的原始文档和基本介绍.今天继续给大家介绍官方文档中,有关可视化的内容.实际上获获取数据和建模更注重业务关系的处理,而可视化则关注对数据的解读.这 ...
随机推荐
- Android开发之使用Handler刷新UI控件
一.为什么必须使用Handler 线程安全问题 这个问题要理解的话很容易,如果没有这个约束,那么同时有两个线程对一个UI控件进行调整,那么控件自然就没法正常的工作,而为了解决这种二义性(就是一个东西同 ...
- python之模块pprint之常见用法
# -*- coding: cp936 -*- #python 27 #xiaodeng #python之模块pprint之常见用法 import pprint data = [(1,{'a':'A' ...
- Linux和windows下内核socket优化项 (转)
问题: No buffer space available Linux: vi /etc/sysctl.conf net.core.netdev_max_backlog = 30000 每个网络接口 ...
- 使用MSTSC远程登录时提示证书无效的解决方法
On your local machine Open Windows command prompt type: gpedit.msc -> Press Enter -> a new win ...
- Window磁盘错误修复chkdsk
场景: 狗日的垃圾移动磁盘.U盘质量太差劲,会出现磁盘坏道.读写异常~心疼数据.... 命令: 01.Win+R 调出cmd 02.根据移动盘符或磁盘盘符,进行修复 03.执行修复chkdsk /f ...
- 【原创视频教程】SqlServer2008视频教程[共9集]
这些视频都是13年-14年两年里面录制的,怀着一份创造之心, 可能说得不对,或者说得肤浅,望见谅....也请指正... 谢谢你的支持.. 更多资料:北盟网 www.bamn.cn ---------- ...
- sqlserver的convert函数
定义和用法 CONVERT() 函数是把日期转换为新数据类型的通用函数. CONVERT() 函数可以用不同的格式显示日期/时间数据. 语法 CONVERT(data_type(length),dat ...
- Linux下Setuid命令! 转载
Linux下Setuid命令! 转载 在Linux系统中每个普通用户都可以更改自己的密码,这是合理的设置. 问题是:用户的信息保存在文件/etc/passwd中,用户的密码保存在文件/etc/sha ...
- Rplidar学习(一)—— 开发套件初识
一.简介 RPLIDAR A1 开发套装包含了方便用户对 RPLIDAR A1 进行性能评估和早期开发所需的配套工具. 用户只需要将 RPLIDAR A1 模组与 PC 机连接,即可在配套的评估软件中 ...
- HDU 4576 Robot (概率 & 期望)
Robot Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others)Total Sub ...