Vuex实践

本文来自网易云社区

做者:刘凌阳

前言

2017年对于Vue注定是不平凡的一年。凭借着自身简介、轻量、快速等特色,Vue俨然成为最火的前端MVVM开发框架。随着Vue2.0的release,愈来愈多的项目开始采用Vue做为他们的前端框架。而做为Vue生态中最重要的一环,Vuex渐渐进入你们的视野。html

数据管理模式前端

在正式开始介绍Vuex以前,有必要介绍一下数据管理模式的前世此生。vue

当你在开发应用程序时,你必定会分解出不少组件进行开发,而各个组件之间想必在逻辑上多少是有关系的。那么组件之间的“通讯”,就成了待解决问题。之前咱们试图用事件广播来作,但随之而来的问题是,在应用不断的扩展、变化中,事件变得愈来愈复杂,愈来愈不可预料,以致于愈来愈难调试,愈来愈难追踪错误。这固然不是咱们想要的,咱们但愿应用的各个部分都易维护、可扩展、好调试、能预测。因而数据管理模式应运而生。git

图1是最简单的组件关系,b是a的子组件,而c是b的子组件。在咱们不引入任何数据管理模式以前,c组件要拿到a组件的数据只能由a先传给b,在由b传给c。若是组件树变得复杂,可想而知这将是一场灾难。看似严谨的父子结构其实严格限制了数据的流动方式。github

图2是最简单的数据管理模式,全部数据将统一交给全局store来管理。a和c组件如今直接修改store里的数据,而且经过mapState从store中抓取本身感兴趣的数据到本身的组件中。而b组件,若是它对a、c组件的数据毫无兴趣,则能够作到彻底解耦。vuex

随着数据管理的进一步发展和演变,有一种叫单向数据流的东西冒了出来。图3就是一个表示“单向数据流”理念的极简示意。单向数据流要求各组件间的数据走向永远是单向的,可预期的。你不能直接改变 store 中的状态。改变 store 中的状态的惟一途径就是显式地提交Actions。这样使得咱们能够方便地跟踪每个状态的变化,从而让咱们可以更好地了解咱们的应用。缓存

此次咱们的主人公Vuex能够说是单向数据流的最佳实践者。前端框架

Vuex是什么?框架

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。Vuex背后的基本思想,就是前面所说的单向数据流。图4就是Vuex实现单向数据流的示意图。异步

接下来,咱们将会更深刻地探讨一些核心概念。让咱们先从Store概念开始。

Store

每个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state) 。

安装 Vuex 以后,让咱们来建立一个最简单的 store。建立过程直截了当——仅须要提供一个初始 state 对象和一些 mutation:



如今,你能够经过 store.state 来获取状态对象,以及经过 store.commit 方法触发状态变动:


因为 store 中的状态是响应式的,在组件中调用 store 中的状态简单到仅须要在计算属性中返回便可。触发变化也仅仅是在组件的 methods 中提交 mutation。

State

Vuex 使用单一状态树——是的,用一个对象就包含了所有的应用层级状态。至此它便做为一个“惟一数据源 (SSOT)”而存在。单一状态树让咱们可以直接地定位任一特定的状态片断,在调试的过程当中也能轻易地取得整个当前应用状态的快照。

那么咱们如何在 Vue 组件中展现状态呢?因为 Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态:


Getter

有时候咱们须要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数:


若是有多个组件须要用到此属性,咱们要么复制这个函数,或者抽取到一个共享函数而后在多处导入它——不管哪一种方式都不是很理想。

Vuex 容许咱们在 store 中定义“getter”(能够认为是 store 的计算属性)。就像计算属性同样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被从新计算。


Getter 会暴露为 store.getters 对象:


Mutation

Vuex 的 store 中的状态的惟一方法是提交 mutation。Vuex 中的 mutation 很是相似于事件:每一个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数(handler)。这个回调函数就是咱们实际进行状态更改的地方,而且它会接受 state 做为第一个参数,payload做为第二个参数(额外的参数):


一条重要的原则就是要记住 mutation 必须是同步函数。  

Action

Action 相似于 mutation,不一样在于:

    1.Action 提交的是 mutation,而不是直接变动状态。 

    2.Action 能够包含任意异步操做。

让咱们来注册一个简单的 action:


Action 函数接受一个与 store 实例具备相同方法和属性的 context 对象,所以你能够调用 context.commit 提交一个 mutation,或者经过 context.state 和 context.getters 来获取 state 和 getters。

咱们能够在 action 内部执行异步操做:

今天的目标


这是一个记忆小游戏,来自leftstick的vue-memory-game,github地址:https://github.com/leftstick/vue-memory-game。今天咱们就这个小游戏来详细讲解下vuex的实现。

组件分解


咱们根据分解图,先把要实现的组件挨个儿列出来:

  1. Game, 最外层的游戏面板

  2. Dashboard, 上面的logo,游戏进度,最佳战绩的容器

  3. Logo,左上角的logo

  4. MatchInfo, 正中上方的游戏进度组件

  5. Score, 右上角的最佳战绩组件

  6. Chessboard, 正中大棋盘

  7. Card, 中间那十六个棋牌

  8. PlayStatus, 最下方的游戏状态信息栏

目录结构

让咱们聚焦红框中关于Vuex的这一部分。接下来咱们将结合Card.vue和Chessboard.vue这两个核心组件进行。

store/index.js


store的建立并无什么复杂的逻辑,而state就是这个项目须要维护的整个数据。初始化cards的结构我简要的整合了一下:


你能够选择初始化store的时候直接带进去,也能够像做者同样从入口处reset一遍数据,这里就不详细展开了。

Chessboard.vue

Card.vue


我在源码上增长了一些注释,方便你们理解。

mapGetter和mapActions只是一些辅助函数,能够减小一些this.$store和dispatch action之类比较重复的代码,这些辅助函数能够帮助vuex应用的更加简便。

相比与这些无关紧要的噱头,咱们更关心卡片被点击的时候发生了什么?this.flipCard()后数据流向了哪里?

数据流动


当卡片被点击时,vue component 实则 dispatch出了一个action,而咱们的数据,做为载荷(参数),也只能随波逐流了。

他首先来到了第一站:actions,然而actions却说你不须要什么异步处理,能够去下一站了。(若是没有异步操做,其实能够少走一站)

 actions处理函数

数据没有灰心,很快他就来到了mutaions。

mutaions欣喜若狂:你在这等着,待我处理好了你再上路。

 mutations处理函数

不一会,数据就改头换面了,但如何告诉vue components我发生变化了呢?迷茫的数据找到了getter。getter哈哈大笑:你在我这的状态存储是响应式的,只要vue components在计算属性中应用了你,他们就能第一时间知道你的状态变动哦。

 

getter生成计算属性(若是没有派生出其余状态,能够不用getter)

 components状态更新


结尾

经过这个记忆小游戏,但愿你们对Vuex有一个基本的理解。若是你熟悉Redux的话,掌握Vuex应该不难,由于Vuex和Redux基本思想是一致的,实现方式也是大同小异。但Vuex只适用于Vue,没有Redux那么泛用罢了。


网易云大礼包:https://www.163yun.com/gift


本文来自网易云社区,经做者刘凌阳受权发布

   


   


相关文章:
【推荐】 如何从“点子”落地到“执行”?—完整解析1个手游传播类mini项目的进化
【推荐】 非对称加密与证书(上篇)
【推荐】 Wireshark对HTTPS数据的解密

相关文章
相关标签/搜索