# 胖模式开发环境及公共组件优化
# 背景
由于胖模式是使用的backbone.js框架,且代码历史悠久,缺失了很多现代化的功能,极大地影响了我们的开发效率,于是对胖模式做了很多优化,下面详细列出:
# 开发环境优化
# 支持mock数据
之前已有创新《模拟胖模式设备cgi程序+前端mock数据》
通过点击页面手动收集接口数据,并上传到服务器提供mock api。
但是由于年久失修,服务器已经挂了,且模拟数据都在服务器不方便实时更新(特别是新接口),所以基于该创新,将mock数据功能本地化:
在build\env.js中提供:
// 开启mock
exports.mock = true;
// mock地址前缀 
const mockVersion = 'wns_sw_ipv6';
只需要开启mock,并配置mock接口的版本,即可跑起胖模式环境,无需依赖后台环境。
# 支持热更新
之前胖模式已经支持本地开启代理服务器,但是使用的是express做服务器,无法监听本地文件的改动,无法做到热更新。
这里引入gulp-webserver插件,开启livereload后可实现代码变动后自动刷新页面。
gulp.src('./')
        .pipe(webserver({
            host,
            port,
            livereload: true,
            open: './index.html',
            directoryListing: {
                enable: true,
                path: './'
            },
            https: {
                key: './build/ca/server-key.key',
                cert: './build/ca/server-cert.crt'
            },
        }))
但是这里有个问题,由于backbone.js框架没使用前端路由,导致刷新后会回到首页。
这里我们通过在菜单的点击事件记录页面路径,存入localStorage中,在热更新时,如果存在该页面记录,则直接打开该页面。
通过以上两种方式,达到类似热更新的效果。
# 接口易于区分
之前接口的url都是https://localhost:8080/cgi-bin/fat_ap.cgi?_t=1715678640549的形式,不同接口完全看不出来哪个是哪个
这里通过拼接上option和opr参数,可以一眼看出接口类型。
# 点击页面跳转至源代码
参考《在页面中快速定位vue组件文件功能》
基本思路是一致的,需要注意的是胖模式都是通过模板渲染,我们只需要解析.tpl文件,给每行拼上代码位置即可。
在gulp-webserver中,通过中间件的形式,拦截请求
gulp.src('./')
        .pipe(webserver({
            middleware: [
                codeServer,
                addCodeLocation,
            ],
        }))
如果是.tpl则拼上代码位置并返回
function addCodeLocation(req, res, next) {
  // 只处理tpl文件
  if (req.url.includes(".tpl")) {
    const filePath = path.join(rootDir, req.url);
    fs.readFile(filePath, "utf-8", function (err, data) {
      const code = data ? codeLineTrack(data, filePath) : data;
      res.end(code);
    });
  } else {
    next();
  }
}
# 增加commit限制
之前胖模式并没有做任何的提交限制,现在换成git后,如果不限制则会导致commit信息杂乱。
安装commitlint、husky
增加commit提交前的钩子,达到校验的效果(例:feat: xxx)。
# 添加eslint
之前的代码也没做任何格式、语法的校验
这里安装eslint
并根据项目适配规则,达到统一代码风格、检查代码错误的效果。
module.exports = {
  root: true,
  env: {
    browser: true,
    node: true,
  },
  extends: ["eslint:recommended"],
  parserOptions: {
    parser: "@babel/eslint-parser",
    ecmaVersion: 6,
  },
  "overrides": [
    {
      "files": ["js/**/*.js"],
      "rules": {
        indent: ["error", 4, { SwitchCase: 1 }],
      },
      parserOptions: {
        ecmaVersion: 5,
      },
    }
  ],
  globals: {
    __: true, // 可以读取,可以修改
    APF: true,
    App: true,
    $: false, // 可以读取,不能修改
    define: false,
    _: false,
    Marionette: false,
    RSAKey: false,
    requirejs: false,
    jQuery: false,
  },
};
# 公共组件优化
# 弹窗层级
之前的弹窗需要在创建时手动指定zIndex。
APF.createDialog(settingForm.$el, {
    zIndex: 302,
})
弊端就是人为去控制,肯定会产生冲突的场景。
这里改成自动生成zIndex,使用弹窗时无需再关心层级问题了。
原理就是记录一个全局变量,每次打开弹窗时就累加,关闭弹窗时就-1
var zIndex = 300;
var getZIndex = function () {
    return zIndex++;
};
var setZIndex = function (_zIndex) {
    zIndex = _zIndex;
};
# 支持插槽渲染组件
backbone没有插槽的概念,小组件复用起来困难,这里我们手动实现一个类似插槽的功能:
在utils中提供渲染插槽函数:
/**
 * 动态渲染组件
 * @param {*} context 父级组件的this
 * @param {*} viewObj 组件配置
 */
utils.renderComponent = function (context, viewObj) {
	var $renderTo = context.$el.find(viewObj.renderTo);
	var view = new viewObj.View($.extend(
		{
			parentView: context,
		},
		viewObj.options || {}
	));
	$renderTo.empty().append(view.$el);
	context[viewObj.viewName] = view;
};
组件配置:
function getIpAddressView (options) {
    return {
        View: Form,
        renderTo: '#ip-address-wrapper',
        options: options,
        viewName: 'ipAddressView',
    }
}
View:backbone框架的一个组件文件,
renderTo:渲染的插槽位置
options: 自定义参数
viewName: 组件实例的变量名
模板:
在模板中预留div,当做插槽
<div id="ip-address-wrapper"></div>
通过以上方法,就可实现类型vue的插槽渲染组件了。
# 表格列文案默认格式化
之前没给列默认的格式化函数,导致无数据时会出现很多空白列
这里统一给上无数据时显示为“-”
# 总结
通过这些优化措施,我们不仅提高了胖模式开发环境的效率和代码质量,还改善了公共组件的复用性和用户体验。