# 胖模式开发环境及公共组件优化

# 背景

由于胖模式是使用的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信息杂乱。

安装commitlinthusky

增加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的插槽渲染组件了。

# 表格列文案默认格式化

之前没给列默认的格式化函数,导致无数据时会出现很多空白列

这里统一给上无数据时显示为“-”

# 总结

通过这些优化措施,我们不仅提高了胖模式开发环境的效率和代码质量,还改善了公共组件的复用性和用户体验。