比较粗糙和浅显,我也只是入门级选手,一知半解,但就此记录一下。
重构评审会
重构理论基础
参考开源框架
1. AbpBase Web iview框架
(我参与的第一个项目就是用的这个框架,配合后端C#的AbpBase框架使用,不知道具体叫啥名字,但就觉得很牛逼,很优雅)
技术栈:Vue + iview + typescript + sass + axios
参考的是此框架对vuex的使用——节选项目中警报管理模块。
结构和代码如下:
// core
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
import alarmManage from './modules/alarmManage'
const store = new Vuex.Store({
state: {
//
},
mutations: {
//
},
actions: {
},
modules: {
alarmManage,
}
});
export default store;
import Entity from './entity'
// 元数据
export default class AlarmManage extends Entity<number>{
Id:number;
deviceName:number;
deptName:string;
deviceType:string;
address:string;
alarmInfo:string;
alarmTime:Date;
remark:string;
status:number;
traceStatus:string;
deviceDisplay:string;
url:string;
}
import {Store,Module,ActionContext} from 'vuex'
import ListModule from './list-module'
import ListState from './list-state'
import Ajax from '../../lib/ajax'
import PageResult from '@/store/entities/page-result';
import alarmManage from '../entities/alarmManage';
// service层
interface AlarmManageState extends ListState<alarmManage>{
playerUrl:string;
}
class AlarmManageModule extends ListModule<AlarmManageState,any,alarmManage>{
state={
totalCount:0,
currentPage:1,
pageSize:10,
list: new Array<alarmManage>(),
loading:false,
}
actions={
async getAll(context:ActionContext<AlarmManageState,any>,payload:any){
context.state.loading=true;
let reponse=await Ajax.get('/api/services/app/AlarmData/GetAll',{params:payload.data});
context.state.loading=false;
let page=reponse.data.result as PageResult<alarmManage>;
context.state.totalCount=page.totalCount;
context.state.list=page.items;
context.state.list.forEach(element=>{
switch(element.status) {
case 0:element.traceStatus="未处理";break;
case 1:element.traceStatus="处理中";break;
case 2:element.traceStatus="已处理";break;
}
});
},
};
mutations={
setCurrentPage(state:AlarmManageState,page:number){
state.currentPage=page;
},
setPageSize(state:AlarmManageState,pagesize:number){
state.pageSize=pagesize;
},
sendUrl(state:AlarmManageState,url:string){
state.playerUrl=url;
}
}
}
const alarmManageModule=new AlarmManageModule();
export default alarmManageModule;
// vue 界面使用
// vue created 调用 actions 请求接口
async created() {
await this.$store.dispatch({
type: "alarmManage/getByFilter",
data: this.pagerequest
});
}
// vue computer 获取state数据
get list() {
return this.$store.state.alarmManage.list;
}
// 调用mutations方法修改数据
pageChange(page: number) {
this.$store.commit("alarmManage/setCurrentPage", page);
this.getpage();
}
2. Le5le Topology拓扑图框架
重构实践
1. 面向对象
以接口响应的数据为核心,提取元数据+元数据的一些增删改查操作,并封装成类。
// 例如我重构的web可视化平台产品,有组态基本信息数据、组态控件数据、组态测点表达式数据……等等
// 以组态控件数据为例,示例代码
import {Pen} from "@topology/core";
import {Store} from 'le5le-store';
// 组态数据
export class TopoDetailData {
// 元数据参数
public pens?: Array<Pen>;
public lineName?: string;
public scale?: number;
public locked?: number;
public bkColor?: string;
public data?: any;
public fromArrowType?: any;
public toArrowType?: any;
public images?: any;
public jsonData?: any;
constructor(data:any) {
// 初始化元数据
this.pens = data.pens ? data.pens : data.jsonData;
this.jsonData = data.jsonData;
this.lineName= data.lineName;
this.fromArrowType= data.fromArrowType;
this.toArrowType= data.toArrowType;
this.scale= data.scale;
this.locked= data.locked;
this.bkColor = data.bkColor;
this.data = data.data;
this.images = data.images;
}
// 元数据增删改查等操作
storeDetailData() {
Store.set('lineName', this.lineName);
Store.set('fromArrowType', this.fromArrowType);
Store.set('toArrowType', this.toArrowType);
Store.set('scale', this.scale);
Store.set('locked', this.locked);
}
}
2. 业务逻辑层面的子组件拆分
比如,一个属性面板,可分类文字属性、动画属性、外观属性、事件属性,那就将其拆分成子组件,解耦。
// 需要主意的是子父组件引用和传值。
3. 复用功能子组件拆分
例如,弹框组件
// 子父组件传值,子组件接收父组件传来的指令,以弹出对应的弹框
@Input()
set visibleModal(val) {
switch (val) {
case 'exportTopo':
this.exportVisible = true;
break;
case 'saveTopo':
this.saveTopoVisible = true;
break;
case 'export':
this.exportVisible = true;
break;
}
}