咱们是否是真的须要状态管理,答案是肯定的,计算你的项目达到了10W行代码,那也并不意味着你必须使用它,应该由业务场景决定。引用Redux的做者Dan Abramov的话说就是: Flux架构就像眼镜,您自会知道何时须要它。Vuex如是也。
目前Vuex在网上争议并不大,用的好的人大有人在,不爱用的人也会使用其余解决方案来作。在《你可能不须要Vuex》一文中,已经对组件化通讯讲的至关明确,也分析了Vuex做为集中式状态管理的好处。然而,大多数文章对具有落地性的Vuex使用场景并无作整理和总结,都是一句“根据应用场景”来收尾。我我的是特别倾向使用Vuex的,他将分散在各处的数据进行集中式统一管理,视图层能够无侵入的接受可预测数据,有效下降耦合,颗粒化的维护各个模块。然而,在咱们的实际开发过程当中,仍然有一些开发者对Vuex存在质疑甚至恨之入骨,这很大一部分缘由是因为我的的编程习惯和学习经验所致,另外一方面也警示着架构须要考虑这些人的问题。javascript
在一开始推广Vuex时,大部分开发人员学习完Vuex后都会向我反馈,说Vuex代码很是的繁琐且冗余,明明能够一行代码解决的,如今代码量和文件量都扩大了。这些开发人员大部分是经历过JQuery时代的悍将,他们早已习惯这种简单粗暴的开发方式,却不多阅读新的知识体系来让本身的技术有所升华。的确,最保守状况下,处理一个组件的数据,咱们须要有一个对应的store
文件,里面包含了state
、getter
、mutation
、action
四个属性,state
定义可预测的数据,getter
提供自动计算的数据,mutation
用于单向改变属性,action
用于发送异步请求,原来一步能够到位的,如今要分红了四步,代码量增长了不说,分文件以后更带来了管理上麻烦。html
Vuex经过定义state
提供组件可预测的数据,当数据是由服务端获取的时候,交由action
来获取便可。然而,一部分人认为,对于列表页面,若是也使用store
,仅仅只是展现数据,除了以前的代码繁琐冗余以外,还会致使内存占用的问题。由于页面切换后,服务端获取的数据并无被释放,仍然存储在state
中,即使从跳转的页面返回,仍然要从新从服务端获取一次最新数据。前端
以上问题,要说是问题还真是个问题,前端架构中除了针对系统应用要有很好的战略布局,对人来讲也要造成必要的约束和规范。针对这些,咱们从前端架构中,增长了对Vuex的扩展,并制定相应的规则来规范开发人员的使用。vue
官网中有针对Vuex的模块化解决方案,这里我就很少赘述了,但官网提供了切割的方式,却没有给出很好的切割的解决方案。在咱们的项目中,咱们将开发的文件夹按照业务进行了划分,每一个业务模块能够独立发布,也能够和其余的模块合并打包。项目的业务模块文件夹以下:java
src - modules ## 模块文件夹 - user ## 用户管理模块 - mock ## 数据模拟 - store ## 数据服务 - view ## 视图 - org ## 组织管理模块 - mock ## 数据模拟 - store ## 数据服务 - view ## 视图 - store-loader.js ## store加载器
全部视图的store模块
是由store-loader.js
加载出来的,它既是状态树的根
,同时又是module state
的加载器,负责将分散在各个模块的store
整合起来。所以,开发人员并不须要维护一个庞大的状态树,而只须要去维护本身的业务模块所需的模块数据便可。webpack
由于webpack工程让js能够提早预编译,因此,咱们的架构中都是让store
和router
分散在各个模块中,编译时整合起来,而且这种整合咱们是按需加载的。ios
咱们的系统中是具有权限管理的,对于某些用户没有该模块的权限,那么这些js文件是不该该加载进来的,虽然会参与编译。在用户登录以后,根据用户权限零时组装store
和router
。一方面让用户资源最小化,一方面也提高了应用性能和安全性。web
咱们的动态加载使用的是store
的registerModule
方法,一样的,对于一些特定路由的数据,在离开后可使用unregisterModule
注销模块,删除数据,避免内存持续占用的问题。vuex
看到以上这些模式,会有人有如下的疑问:shell
由于咱们的项目架构把router
混合在了view
中,把api/services
混合进了store
中。前面的混合我会讲一个专题来解释为何要这么作,后面的混合就是为了一部分解决以前咱们提到的开发人员所遇到的痛点问题。咱们能够来看以下案例:
import api from '@src/api/counter'; const store = { state: { count: 0 }, mutations: { setCount (state, count) { state.count = count; } }, actions: { loadCount ({commit}) { api.loadCount().then((count) = { commit('setCount', count); }) } } };
api
中经过axios
向服务端发起请求获取数据:
// @src/api/counter.js import axios from 'axios'; export default { loadCount: () => axios.get('/api/counter') };
对于api/serives
,太薄了,仅仅只是对axios
进行了一个函数的包裹,而中间咱们没有加入任何的逻辑,也不该该加入逻辑。这样作一方面不便于管理,也没办法发挥api
的意义。因此,咱们将api
整合进了store
,对于仅仅用于展现的组件来讲就更加便利了,不须要定义state
、mutation
,直接经过action
返回promise
,交由组件去使用。
通过以上的思路,咱们让代码尽量的内汇集中,同时又分散耦合,配合服务端将加载量下降,经过架构中的模块让代码量也适当下降。当开发量变得巨大的时候,这种方式会下降不少度复杂度,让开发变得高效顺畅。