vue 项目代码拆分的方案
作者:Chieffo 发布时间:2024-06-05 09:17:56
目录
背景
目的
拆分前
流程设计
目录结构设计
存在的问题
拆分后
流程设计
目录结构设计
解决的问题
关键代码
总结
其他实现方式
背景
由于之前的数据库防火墙产品与数据库审计产品使用的是同一套代码,随着两个产品功能的差异越来越大,代码的冗余度和偶合度越来越高,为了便于后期维护以及添加新功能,所以基于原来的项目代码,进行了代码结构拆分。
注意:本次拆分只拆分了可以拆分的部分,有的模块例如:规则、关于我们,是没有进行拆分的,一是有的模块很简单,没必要拆分;二是有的模块原先写得代码偶合太严重,无法拆分,如果要拆分,需要花费大量精力去梳理代码,同时还要后端配合拆分。
目的
将此次代码拆分方案记录下来,便于后来的开发人员快速熟悉项目结构。
拆分前
流程设计
项目拆分前,区分数审和防火墙功能的流程如上图所示。
访问系统时,先加载入口文件 main.js,然后加载登录页 login.vue,加载登录页的同时获取产品模式并保存到 session.storage.platformType 中,接着用户登录系统进入具体页面,该页面同时包含了数审和防火墙的功能,根据 session.storage.platformType 保存的值来判断,具体显示哪个功能。
目录结构设计
项目拆分前的目录结构如上图所示。
该目录结构是初始化一个 Vue 项目时的基本目录,根据目录结构,基本上看不出该项目包含了两个不同的产品,也不知道不同产品模式下会加载哪一部分文件,结构不清晰。
存在的问题
通过分析,可以发现当前的系统流程和目录结构是存在很多问题的,大概总结下:
加载登录页的时候才获取产品模式,如果登录页加载完成,而产品模式还未获取或者获取不到,那么登录页显示的产品信息有可能是错误的;
每次进入一个具体页面,如果同时包含了数审和防火墙的功能,都要重新判断一次,当前的功能是数审的还是防火墙的;
目录结构不清晰,不清楚哪些模块是公共模块,哪些是数审独有的模块,哪些是防火墙独有的模块;
可维护性和可扩展性差。数审的代码和防火墙的代码混在一个文件内,改代码的时候需要重头看一遍才知道哪块代码属于数审,哪块代码属于防火墙。如果想要添加一个功能,还得继续加逻辑判断,代码越来越臃肿;
业务逻辑混乱,与后端通信使用了同一个接口。
拆分后
流程设计
项目拆分后,区分数审和防火墙功能的流程如上图所示。
访问系统时,先加载入口文件 main.js,该文件中写了路由拦截相关的逻辑,在路由拦截时,如果没有产品模式,则要先获取产品模式,否则会被拦截,进不去系统。获取产品模式后,根据当前产品模式,会注册对应的登录页、路由配置、接口请求等。当注册完毕后,每次访问具体的页面,都应该是独立的模块了。
目录结构设计
项目拆分后的目录结构如上两个图所示。
该目录结构经过拆分,已经可以清晰地看到不同产品之间分离出来的文件了,从入口文件开始,经过路由拦截后,会加载指定的登录页,然后把对应产品需要的文件合并到公共文件中。比如:http 请求、路由配置等。最终结果,程序只会把需要的文件加载进去。
解决的问题
经过重新设计,解决了当前项目存在的一些问题:
在加载登录页之前,通过路由拦截,必须先获取产品模式,才能进入系统,登录页是在获取到产品模式之后才加载的,不会出现产品信息显示错误的问题;
只有在第一次进入系统或刷新页面的时候,才会重新获取产品模式,合并产品模式对应的文件,合并的文件是拆分后的文件,不需要在文件内再次判断该有数审的功能还是防火墙的功能。
目录结构清晰,防火墙相关的功能模块文件都放在 views-fw 文件夹内。
提高了项目的可维护性和可扩展性,降低了代码的偶合度。数审的代码和防火墙的代码基本已经拆分开,如果想要添加一个防火墙的功能,只需要在防火墙相关的文件夹内新增对应功能模块的文件即可。
业务逻辑清晰,与后端通信使用的是不同的接口,公共模块使用的接口按原来的不变,数审独有的接口在 url 前面增加了 audit 前缀,防火墙独有的接口在 url 前面增加了 firewall 前缀。
关键代码
/**
* @Name: main.js
* @Author: cqfeng
* @Description: 项目入口 js 文件
* @MainFunction: 引入和注册一些全局资源
**/
//...省略的代码...
// 路由拦截,使用全局导航守卫beforeEach
router.beforeEach(async (to, from, next) => {
// 如果没有产品模式,先获取产品模式
if (!store.state.productMode.productMode) {
await store.dispatch('productMode/SET_PRODUCT_MODE');
}
//...省略的代码...
/**
* @Name: product-mode.js
* @Author: cqfeng
* @Description: 产品模式相关逻辑处理文件
* @MainFunction: 保存当前产品模式,根据不同产品模式配置 产品登录页、http 请求 等资源
**/
import Vue from 'vue';
import portService from '@/assets/js/service/http/http'; // axios请求
import router from '@/router/index'; // 默认路由配置,动态路由配置
import httpAAS from '@/assets/js/service/http/http-aas'; // 数审独有的 http 请求
import httpFW from '@/assets/js/service/http/http-fw'; // 防火墙独有的 http 请求
import globalConstant from '@/assets/js/const/global-constant'; // 项目全局常量
export default {
namespaced: true,
state: {
productMode: '', // 产品模式,进入系统或刷新页面时获取
},
mutations: {
// 修改产品模式
changeProductMode: function (state, value) {
state.productMode = value;
},
},
actions: {
async SET_PRODUCT_MODE({ commit, state }) {
let res = await portService.getProductMode();
if (res.data.code === 0) {
commit('changeProductMode', res.data.data.productMode);
}
// 如果是数审产品
if (state.productMode === globalConstant.COMMON.AAS) {
// 设置产品登录页
router.addRoutes([
{
path: '/login',
name: 'login',
component: resolve => {
require(['@/views/login.vue'], resolve);
},
}
]);
// 合并 http 请求,挂载到 Vue 原型上
Vue.prototype.portService = Object.assign(portService, httpAAS);
}
// 如果是防火墙产品
else if (state.productMode === globalConstant.COMMON.DBSG) {
// 设置产品登录页
router.addRoutes([
{
path: '/login',
name: 'login',
component: resolve => {
require(['@/views/views-fw/login.vue'], resolve);
},
}
]);
// 合并 http 请求,挂载到 Vue 原型上
Vue.prototype.portService = Object.assign(portService, httpFW);
}
}
}
};
总结
经过拆分,数审和防火墙的代码目录已经算是基本分开了,这个过程花费的力气也很大,也引发了我的一些思考,一套代码多个项目的这种方案是否算好的方案,还有没有其他更好的方案。如果项目一开始,就按照一套代码多个项目的设计来开发,会不会后期的维护成本会低一些?这些问题我也没有答案,希望后来者能够继承历史经验,更好地开发出优秀的项目。
其他实现方式
起初设计拆分方案的时候,有两种方案,一种是通过获取产品模式动态改变当前产品功能,一种是在打包时通过打包参数打包指定产品包。最终的方案是选择第一种。但是,在这个过程中也参考了一些网上的实现方案,这里列出来方便以后需要用到进行参考。
//www.aspxhome.com/article/188869.htm
//www.aspxhome.com/article/207835.htm
来源:https://segmentfault.com/a/1190000039416110
猜你喜欢
- 效果如下图:当点击问题时显示下面的回复内容。script type="text/javascript"> onlo
- 之前博客有用logstash-input-jdbc同步mysql数据到ElasticSearch,但是由于同步时间最少是一分钟一次,无法满足
- 问题概述今天在上班时,DBA突然找出来一段sql,表示该sql存在隐式转换,不走索引。经过我们的查看后,发现是类型varchar的字段, 我
- 投资有风险,选择需谨慎。 股票交易数据分析可直观股市走向,对于如何把握股票行情,快速解读股票交易数据有不可替代的作用!1 数据预处
- 我们使用pycharm的时候,有时遇到了不认识的方法习惯于将鼠标悬停在方法上查看方法介绍。那么如何设置呢?下面小编给大家分享一下。首先假如我
- 概述Go 的并发模型与其他语言不同,虽说它简化了并发程序的开发难度,但如果不了解使用方法,常常会遇到 goroutine 泄露的问题。虽然
- 1. 反射简介1.1 反射是什么?Go语言提供了一种机制在运行时更新和检查变量的值、调用变量的方法和变量支持的内在操作,但是在编译时并不知道
- 前几天看到某论坛有人提了这么个问题,Python这么火,为啥找工作这么难呢? 这两年因为第三波人工智能热潮让 Python火了一把
- 目录一、索引类型1.B+树2.MyISAM和InnoDB的B+树索引实现方式的区别(聚簇索引和非聚簇索引)?3.非聚簇索引4.聚簇索引的优缺
- 首先明确为什么要使用分页查询,因为数据庞大,查询不可能全部显示在页面上,如果全部显示在页面上,也会造成查询速度慢的情况,所以分页查询解决了①
- 功能是打开本机端口,映射到指定IP的端口场景1本机:tomcat启动8080,通过本端口工具打开80,指向到tomcat的8080。请求本机
- 如果要问做什么事是最有吸引力,那就是创建Web应用。Web设计者们对设计交互式的Web没有什么更好的办法,却对我们做桌面软件的同事投去少许羡
- 【问题原因】 这个应该是 jquery.datatable 控件本身的一个缺陷。 该控件中的checkbox小插件的id是写死的,所以当有多
- 初学OpenCV图像处理的小伙伴肯定对什么高斯函数、滤波处理、阈值二值化等特性非常头疼,这里给各位分享一个小项目,可通过摄像头实时动态查看各
- 本文实例讲述了js树插件zTree获取所有选中节点数据的方法。分享给大家供大家参考。具体分析如下:由于刚接触Tree方面的东西。在网上看到了
- pytest概述pytest是一个非常成熟的全功能的Python测试框架,主要特点有以下几点:1、简单灵活,容易上手,文档丰富;2、支持参数
- 配置指令如下:[opcache]zend_extension=opcache.soopcache.enable_cli=1;共享内存大小,
- 一、项目概述本次项目目标是实现对自动生成的带有各种噪声的车牌识别。在噪声干扰情况下,车牌字符分割较困难,此次车牌识别是将车牌7个字符同时训练
- 前言使用python实现设计模式中的单例模式。单例模式是一种比较常用的设计模式,其实现和使用场景判定都是相对容易的。本文将简要介绍一下pyt
- 举个简单的例子:(此仅限于修改change_form页面)原来的时候,change_form_list是包含这些按钮的:因为此页面继承了{%