源码地址:https://github.com/18291907191/gwc_manage
Vue实战狗尾草博客后台管理平台第七章
本章内容为借助模块化来阐述Vuex的进阶使用。
在复杂项目的架构中,对于数据的处理是一个非常头疼的问题。处理不当,不仅对维护增加相当的工作负担,也给开发增加巨大的压力。
在大量的实战开发过程中,狗尾草总结出来的较为友好的方式是 使用一个单独的数据管理库去管理数据。
这样不会给页面增加额外的负担。且API的调用也属于数据处理/获取的部分。因此也放在数据管理下统一管理
注:本章节内容与狗尾草博客管理平台没有任何关系,仅作为Vuex的进阶使用来分享
对模块化的简单阐述
在开始时,我们需要先对模块对有一个清晰的定义!
这里不扯AMD与CMD规范。
简单论述为:对于复杂系统的开发。制作清晰的分界。广义上讲就是将一湖的水进行"渠道化分流"。但是微观上确实有非常多的东西,且可以根据具体的项目进行具体的场景分析从而进行设计。
上面所说也可以理解为模块的理解或者使用场景。
如何实现
在平时的开发中,我们可以对什么进行模块化?
我们需要一个目标,这个目标作为系统来理解。那我们就必须知道的是,我们的系统有哪些功能与业务。必须有一个清晰的四位导图来支撑。
就平常的系统来讲。所必需的的有不同功能的业务。这些业务在是实现的过程中,又分为:view,style,js。这些又可以进行划分为:组件的抽离,样式的抽离,工具类的抽离,静态资源的抽离。再次基础上一个页面就已经可以呈现到屏幕上了。但是他还是静态的,还是由我们Mock数据所支撑。并无鲜活数据的支撑。此时。我们就可以对数据进行抽离。
为什么要做模块化抽离?或者说这样做有什么好处呢?
简单说模块化意义就在于数据的可视化,便捷的管理,数据的挖掘,系统的维护,系统更为清晰的架构。当然其真实的意义与优势只有在具体的开发并实践后才有所呈现。且会根据不同系统呈现不同结果。你永远不会知道这么做会给你带来什么Surprise!
补充:让开发者对系统有更好的可控性,或许这也是模块化的意义之一。
API抽离
请求接口抽离,作为单独模块进行统一的管理,对于后端接口的服务,在前端也会有更好的结构认识。同时在使用时也会更加便捷。
eg:
commons下可以放置我们共用的一些api模块
modules则可以对api再次进行模块化划分。
比如后端的接口服务有a服务,b服务,c服务。name我们也就可以按照a服务,b服务,c服务进行划分。
但是这里狗尾草不建议这样来配置。因为后端所用服务并不定是我们需要的。其命名也经常是一些生僻的单词,尝尝会令新加入的developer感到无力。
这里狗尾草提出的一个合理化的解决方案便是根据前端的项目的业务来划分或者前端的服务来划分。比如说用户服务(登录,注册,修改,忘记密码,权限,个人信息等),文章服务(标题,内容,更改,删除,草稿等等)。
当然这里提出的合理化的解决方案不仅如此,我们也需要在项目的README.md的文件中对api模块的划分做出合理的解释。这样对于新加入项目的同事也不会有太大的困惑。
base.js的话我们则可以进行域名的配置。根据项目不同的环境进行动态的配置。开发环境的域名,测试环境的域名。预发布环境的域名,生产环境的域名等等。这里又可以通过不同的启动命令来动态配置。(这里的配置因为每个脚手架所创建项目各有所异。因此暂不做详情说明)
api的配置结束,我们就需要一个出口文件,供其他模块进行调用。index.js则是一个很好的出口。
import serverA from './modules/serverA';
import serverB from './modules/serverB';
export default {
serverA,
serverB
}
这样一个api模块,我们就简单的抽离了出来。剩下的至于在项目中怎么使用,我们就不需要过多操心。但是好的方式的挂在global下,供全局的更为便捷的使用。
例如在Vue中,我们便可以通过install到Vue.prototype上来实现
import api from '@/api';
const install = (Vue,opts = {}) {
if (install.installed) return;
Vue.prototype.$api = api;
}
export default install;
main.js
import Utils from './utils';
Vue.use(Utils);
this.$api.模块.具体的api接口 用此方式便可更为方便的对api进行使用。当然有一个缺点是过多的东西挂载在原型链上。Vue的性能则会受到影响,但是相较于系统中频繁操作的api来言。却可以省略了。
当然API的抽离也仅仅是繁多模块化开发中的一个。
Pages抽离
Pages抽离其实并无特殊的意义,理解成本意就好。页面的抽离
这里的页面的抽离,我们则不能通过功能来进行拆分了,我们需要根据业务来走啦。
给大家一个最直观的理解:大家可以看看管理系统的菜单栏部分。一级菜单,二级菜单等等。大家的业务的流程便可以根据这些来走。
每个一级菜单作为一个大的pages来抽离
页面的设计架构我们便可以如此进行:
pages
pages1
components
data
router.js
static
pages2
components
data
router.js
static
简单阐述就是多个大型的业务模块。具体拆分为多个页面模块,此多个页面模块的路由在此业务下统一管理,常量资源,业务的Private Component,数据的管理也都在此模块下做统一处理。
其意义直观上来看,多个业务之间并无任何的耦合。并不会造成业务逻辑样式等得污染。
Router抽离
创建主路由并创建拦截,以拦截做出路由的主出口。
在此基础上对各个业务模块进行单独的路由拆分,以达到模块抽离的各个方面,并将模块使用到其他项目中,也依然可以使用。
eg:
Router/index.js主路由
import Vue from 'vue';
import Router from 'vue-router';
import { Route as RouterA } from '@/pages/xxx';
import { Route as RouterB } from '@/pages/xxx';
Vue.use(Router);
export const constantRouterMap = [
路由的配置
...RouterA,
...RouterB,
]
模块化中的路由拆分,我们则可以认为模块化中的路由为此模块的入口
eg: 某模块的入口
Modeal/index.js
export const Route = [
{
xxx:xxx路由配置
}
]
入口已配置,剩下的就在上述的代码中操作加入总的路由中,在后续路由的更改时,只需要在相应的模块中修改即可。减少了很大程度上的耦合。
基本的模块的开发就如上述那样,循规蹈矩,却又加入项目场景,经过深思熟虑做出合理魔窟阿化!
下来也就是本章的另一个重点。Vuex的进阶使用。
数据的统一管理之Vuex的进阶使用
基础的东西不多做解释,大佬们都懂得。Vuex为Vue提供了很好的数据管理方式。
Vuex is a state management pattern + library for Vue.js applications.
在使用之前,我们必须先思考,我们用它可以干什么?
简单举例来说明:
如果没有这样的一个数据的管理库,那么我们在开发时,不可避免的要经历这样的过程。n多页面之间共享数据,或组件间数据的传递。a传b,b传c,c传d,甚至会更加复杂。
从数据管理的第三方库出来后,我们便不需要这种的方式进行数据的传输。
Vue中的Vuex,React中的Redux。
Vuex的简单的流程
State: 数据的存储
Getters:state中数据的过滤,更便捷的获取
Mutations: state中数据的操作
Actions:异步请求的操作,可以理解为数据的init
modules:状态库的模块化管理
使用的流程串起来简单说就是 view 读取state数据并进行render。交互操作时,通过mutations对state数据进行更新。页面初始化派发action请求获取初始化数据。
多个页面之间需要共享数据时,只需要从store中取值就好。
当项目复杂程度较小时,我们可以在根目录下通过store/modules的结构来拆分状态库,通过index.js来提供主出口即可。
前几篇文章中使用到的store的使用就是如此。
但是当项目复杂度提升时,我们就必须设计插拔式管理。
import Vue from 'vue';
import Vuex from 'vuex';
import storeA from '@pages/xxx/store';
Vue.use(Vuex);
export default new Vuex.Store({
xxx,
xxx,
xxx,
xxx,
modules: {
...storeA
}
})
将store的管理也进行拆分管理。对组件化,模块化更深层次的配置。使各个模块在互相不依赖的情况下,也依旧不影响使用。低耦合,高复用!
如果需要对store做一个总结的话,那就是每个Pages模块拥有自己的状态管理库,自己的常量配置,自己的私有组件,在任何情况下,每个模块都能独立运行。无疑是对高复用,低耦合的很好的实现.
具体使用场景如下:
eg:
import { mapGetters,mapActions, mapMutations } from 'vuex';
computed: {
...mapGetters('模块名',['state1','state2'])
},// state的映射,在不同模块中,取出不同的模块下的数据
...mapActions('模块名',['request1','request2']),//映射出相关模块下对应的异步请求,并在需要的时候派发出去。
...mapMutations('模块名',['stateopt1','stateopt2']);//对state的操作也可以在页面中进行。但是一般不建议在页面中对state进行操作。