作者:陈剑冬  历史版本:1  最后编辑:陈剑冬  更新时间:2024-05-27 18:46

本文包含一份将VUE 2单文件组件迁移为BI自主分析工具组件库组件的迁移指南,帮助组件开发者完成迁移工作。

示例代码

本示例代码无任何 components 子组件依赖。

<template>
  <div class="wh-control">
    <el-input v-model="temp.value"
              @input="setVal"
              class="input-with-select"
              style="width: 122px;float: right;">
      <el-select v-model="temp.unit"
                 filterable
                 allow-create
                 placeholder=""
                 size="mini"
                 slot="append"
                 @change="setUnit">
        <el-option v-for="item in options"
                   :key="item.value"
                   :label="item.label"
                   :value="item.value"></el-option>
      </el-select>
    </el-input>
  </div>
</template>
<script>
import { formatCalc } from '../core/canvasUtils.js';
import { isNumber } from 'lodash-es';

export default {
  props: ['data', 'units', 'width', 'range', 'isOnlyPx'],
  data() {
    return {
      temp: {
        value: '',
        unit: '',
      },
      options: [
        {
          label: 'px',
          value: 'px',
        },
        {
          label: '%',
          value: '%',
        },
      ],
    };
  },
  model: {
    prop: 'data',
    event: 'input',
  },
  computed: {
    /**
     * @returns {string}
     */
    rawSize() {
      //对echart类组件的某些数值尺寸兼容
      if (isNumber(this.data)) return this.data + 'px';
      return this.data.toString();
    },
  },
  watch: {
    rawSize: {
      handler(newValue, oldValue) {
        this.getVal();
      },
      deep: true,
    },
  },
  created() {
    if (this.units) {
      let ops = [];
      for (let i in this.units) {
        ops.push({ label: this.units[i], value: this.units[i] });
      }
      this.options = ops;
    }
    this.getVal();
  },
  methods: {
    getVal() {
      let wh = this.rawSize;
      if (wh) {
        if (wh.indexOf('calc') != -1) {
          this.temp.unit = 'calc';
          this.temp.value = wh.replace('calc(', '').replace(')', '');
        } else if (wh.indexOf('px') != -1) {
          this.temp.unit = 'px';
          this.temp.value = wh.replace('px', '');
        } else if (wh.indexOf('%') != -1) {
          this.temp.unit = '%';
          this.temp.value = wh.replace('%', '');
        } else if (wh.indexOf('rem') != -1) {
          this.temp.unit = 'rem';
          this.temp.value = wh.replace('rem', '');
        } else if (wh.indexOf('em') != -1) {
          this.temp.unit = 'em';
          this.temp.value = wh.replace('em', '');
        }
      }
    },
    setVal() {
      let value = '';
      if (this.temp.unit === 'calc') {
        value = formatCalc('calc(' + (this.temp.value || 0) + ')');
      } else if (this.temp.unit === 'px') {
        const valInput = this.temp.value.replace(/[^-\d.]/g, '');
        const valInt = Number.isNaN(Number.parseInt(valInput)) ? 0 : Number.parseInt(valInput);
        if (this.range) {
          if (typeof this.range.min !== 'undefined' && valInt < this.range.min) {
            this.temp.value = this.range.min;
          } else if (typeof this.range.max !== 'undefined' && valInt > this.range.max) {
            this.temp.value = this.range.max;
          } else {
            this.temp.value = valInt;
          }
        } else {
          this.temp.value = valInt;
        }
        value = (this.temp.value || 0) + this.temp.unit;
      } else {
        this.temp.value = this.temp.value.replace(/[^\d.]/g, '');
        value = (this.temp.value || 0) + this.temp.unit;
      }
      this.$emit('input', value);
    },
    setUnit() {
      if (this.isOnlyPx) {
        this.temp.unit = 'px';
      } else {
        if (this.temp.unit === 'calc') {
          this.temp.value = this.rawSize;
        } else if (this.temp.unit.indexOf('em') != -1) {
          this.temp.value = '10';
        } else {
          if (this.temp.value.indexOf('%') != -1 || this.temp.value.indexOf('px') != -1) this.temp.value = '100';
        }
      }
      this.setVal();
    },
  },
};
</script>
<style lang="less"  scoped>
.wh-control {
  ::v-deep.el-select {
    width: 50px;
    .el-input {
      .el-input__inner {
        padding-right: 12px;
        border-color: transparent;
        .el-input__suffix {
          top: 0;
          right: 0;
          .el-select__caret {
            line-height: 24px;
            font-size: 12px;
            color: #82828d;
          }
        }
      }
    }
  }
  .el-input-group__append,
  .el-input-group__prepend {
    background-color: #ffffff;
  }
}
</style>

开始迁移

新建通用组件

填写基本信息

填写组件基本信息,包含组件分类、组件名称、组件图标(支持svg、png图片文件);若未提供组件图标,当组件保存时,系统将根据组件渲染结果生成组件缩略图作为组件图标。

迁移内容

复制 vue 模板

删除系统初始化的HTML模板内容,复制现有组件模板内容到组件模板编辑器内,如下图:

注意:请保留一个div元素作为现有组件模板根元素的父级,否则组件将无法正常渲染。

复制组件样式

删除系统初始化的样式表内容,复制现有组件的样式表内容到组件样式编辑器内,如下图:

注意:如果现有组件的样式表语法不是这三种其一,请手动改写为符合这三种样式表语法的样式表声明。

组件样式编辑器支持 sass/scss/css三种样式表语法,我们建议使用scss语法编写。

同时,为了该组件的样式表样式不会污染其他组件样式,应使用同一个根类选择器编写组件样式表。同时将该根类选择器名称添加到组件模板中的根元素,如模板下图:

复制组件脚本

上述组件模板、组件样式表迁移完成后,则可以开始组件脚本迁移工作。
首先清理系统初始化的组件脚本内容,如下图:

import 依赖库导入

  1. js模块导入
    使用组件依赖引入js模块,请查看 【引入第三方js模块】 文章。

    注意:与本地IDE开发不同,在BI自助分析工具中组件调用其他js模块时只能通过全局对象或命名空间进行调用。
    例如示例中使用的 loadash 模块的 isNumber 函数,应下载lodash对应的浏览器模块文件,添加为组件依赖,然后在通过window.lodash.isNumber调用lodash模块。

  2. 样式表导入
    暂时不支持样式表导入,请将组件依赖的样式表内容复制到样式表编辑器内。

components 子组件引用

子组件依赖迁移,请查看 【子组件components用法】 文章。

修改组件 prop 编写方式

将现有组件prop声明改为BI自助分析工具中组件属性定义,如下图:

修改模板中prop取值字符串,修改prop名称.value,以正确获取其值。

注意:每个prop声明都应转为如上图所示的属性定义对象。

修改组件 data 编写方式

将现有组件data中的字段声明改为BI自助分析工具中的组件属性定义,如下图:

修改模板中data字段取值字符串,修改data字段名.value,以正确获取其值。

注意:每个data字段都应转为如上图所示的属性定义对象。

修改组件 computed 编写方式

将现有组件computed字段声明复制到BI自助分析工具vue组件创建api参数中,该api调用通常在BI分析工具组件 init(初始化)函数的起始位置,如下图:

注意上图中的lodash模块调用方式已从import导入更改为组件依赖导入的方式。不过,由于BI自助分析工具中已内置lodash模块,因此我们可以直接调用,而不必有添加组件依赖。
同时注意,名称为data的prop取值也迁移为this.data.value。

修改组件 watch 编写方式

将现有组件watch声明复制到BI自助分析工具vue组件创建api参数中,该api调用通常在BI分析工具组件 init(初始化)函数的起始位置,如下图:

修改组件 created 编写方式

将现有组件created声明复制到BI自助分析工具vue组件创建api参数中,该api调用通常在BI分析工具组件 init(初始化)函数的起始位置,如下图:

同样注意,prop或data取值也应迁移BI自助分析工具组件属性的取值方式,即在原有字段名后添加.value。

修改组件 mounted 编写方式

将现有组件mounted声明复制到BI自助分析工具vue组件创建api参数中,该api调用通常在BI分析工具组件 init(初始化)函数的起始位置,如下图:

示例组件未声明mounted生命周期回调, 因此这里保持为空,仅为示例读者。如果正在迁移的组件也没有回调,则可省略。

修改组件 methods 编写方式

与created、mounted类似,将现有组件methods声明复制到BI自助分析工具vue组件创建api参数中,该api调用通常在BI分析工具组件 init(初始化)函数的起始位置。

同样注意,prop或data取值也应迁移BI自助分析工具组件属性的取值方式,即在原有字段名后添加.value。

修改组件 emit 编写方式

现有组件包含emit事件通知时,需要将其转换BI自助分析工具组件的事件函数,如下图:

即定义input事件函数,并将this.emit改为this.$com.method.input调用,当该组件作为子组件时,当父组件在组件模板中@input则可以收到子组件input事件通知。

注意:input事件函数声明语法,请务必采用该语法声明事件函数。

测试与调试

完成上述迁移工作后则进行组件开发调试,读者可以通过浏览器开发者工具进行调试。