Skip to content

业务组件开发与上传指南

在前面的章节中,我们已经介绍了如何上传一个基础组件。然而,在企业实际开发场景中,我们通常需要开发和共享具有实际业务价值的组件。本文将详细介绍如何在 comp-hub 平台上开发和上传业务组件。

工程化环境下组件开发的挑战

在传统工程化环境中开发 Vue 组件时,通常需要考虑以下几个关键要素:

1. 组件依赖资源

  • 静态资源:如图像、图标等通常存放在项目的 assets 目录中
  • 全局工具函数:如日期处理、数据转换等实用函数通常位于 utils 目录

2. UI 库集成

  • 现代前端开发普遍依赖 UI 组件库(如 Element UI、Ant Design Vue 等)
  • 组件通常会复用这些 UI 库提供的基础组件

3. CSS 预处理器

  • 开发中常使用 SCSS、Less 等预处理器提高样式开发效率
  • 预处理器提供的变量、嵌套、混合等特性极大提升了样式代码的可维护性

4. 第三方依赖

  • 组件可能需要引入专业库,如数据可视化库(ECharts)、日期处理库(dayjs)等

comp-hub 平台的组件规范

comp-hub 平台设计的目标是在保证组件可移植性的同时,尽可能保留开发者熟悉的开发体验。因此,除了基础组件上传规范外,业务组件还需要遵循以下特殊规范:

  • 资源自包含:组件依赖的所有资源必须包含在组件文件夹内,且必须使用相对路径引用,不支持路径别名
  • UI 库支持:目前平台仅支持 Element UI(Vue 2)和 Element Plus(Vue 3)
  • UI 组件规范:使用 UI 库时,必须遵循官方推荐的组件使用规范,以便平台正确识别和适配
  • CSS 预处理器:目前仅支持 SCSS 预处理器

开发业务组件实例

接下来,我们将按照平台规范开发一个具有实际业务价值的组件。我们选择开发一个日活率显示组件,这是数据可视化中常见的业务需求。

组件预览

日活率组件效果

这是一个基于 ECharts 开发的日活率显示组件,具有以下特点:

  • 使用环形图展示数据比例
  • 包含图例说明不同数据类别
  • 中间显示核心指标数值
  • 具有旋转背景动画效果
  • 支持响应式调整大小

组件目录结构

遵循 comp-hub 规范的组件目录结构如下:

QinParamRatio/          # 组件根目录(名称即为组件名)
├── demo/               # 示例目录
│   ├── full.vue        # 全屏预览示例
│   └── index.vue       # 小窗预览示例
├── img/                # 图片资源目录
│   └── bg.png          # 背景图片
├── comp.json           # 组件配置文件(由平台自动生成)
├── index.vue           # 组件入口文件
└── README.md           # 组件文档

组件实现代码

以下是 index.vue 的完整实现代码,包含模板、逻辑和样式:

vue
<template>
  <figure class="ratio" :style="cssVar">
    <!-- 图例 -->
    <figcaption class="ratio__legend">
      <span v-for="i in legend" :key="i.name" class="ratio__tag" :style="{ '--c': i.color }">{{ i.name }}</span>
    </figcaption>

    <!-- 旋转背景 -->
    <img class="ratio__bg" :src="bgIcon" />

    <!-- 中心文字 -->
    <figcaption class="ratio__title">
      <b>{{ title }}</b>
      <em>{{ val }}</em>
    </figcaption>

    <!-- 图表容器 -->
    <div ref="chart" class="ratio__chart"></div>
  </figure>
</template>

<script>
// 导入第三方库
import * as echarts from "echarts";
// 使用相对路径导入图片资源
import bgIcon from './img/bg.png'

export default {
  // 组件名称
  name: 'QinParamRatio',
  
  // 组件接收的属性
  props: {
    // 图例配置
    legend: {
      type: Array,
      default: () => [
        { name: '注册用户1', color: '#082847' },
        { name: '日活用户1', color: '#0e8d5e' }
      ]
    },
    // 标题文本
    title: { type: String, default: '日活率' },
    // 核心数值
    val: { type: Number, default: 100 },
    // 组件尺寸
    size: { type: Number, default: 250 }
  },
  
  // 组件数据
  data() {
    return { 
      bgIcon, // 图片资源
      chart: null // ECharts 实例
    }
  },
  
  // 计算属性
  computed: {
    // 动态 CSS 变量
    cssVar() {
      return {
        '--size': this.size + 'px',
        '--inner': Math.round(this.size * 0.7) + 'px'
      }
    }
  },
  
  // 生命周期钩子
  mounted() {
    this.init() // 初始化图表
    window.addEventListener('resize', this.resize) // 监听窗口大小变化
  },
  
  // 组件销毁前清理资源
  beforeDestroy() {
    window.removeEventListener('resize', this.resize) // 移除事件监听
    if (this.chart) {
      this.chart.dispose() // 销毁 ECharts 实例
    }
  },
  
  // 组件方法
  methods: {
    // 初始化图表
    init() {
      this.chart = echarts.init(this.$refs.chart)
      this.chart.setOption({
        color: this.legend.map(i => i.color),
        series: [{
          type: 'pie',
          radius: ['60%', '70%'],
          startAngle: 220,
          endAngle: -40,
          padAngle: 5,
          label: { show: false },
          data: this.legend.map(i => ({ name: i.name, value: 1 }))
        }]
      })
    },
    
    // 响应窗口大小变化
    resize() {
      if (this.chart) {
        this.chart.resize()
      }
    }
  }
}
</script>

<style lang="scss" scoped>
/* ---------- CSS 变量定义 ---------- */
.ratio {
  --size: 250px;
  --inner: 175px;
  --font-xs: 12px;
  --white: #fff;
  --orange: #fda843;
}

/* ---------- 组件布局样式 ---------- */
.ratio {
  position: relative;
  width: var(--size);
  height: var(--size);
  margin: 0;
}

.ratio__legend {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  justify-content: center;
  gap: 10px;
  font-size: var(--font-xs);
  color: var(--white);
}

.ratio__tag {
  display: flex;
  align-items: center;

  &::before {
    content: '';
    width: 3px;
    height: 12px;
    margin-right: 4px;
    background: var(--c); // 使用 CSS 变量动态设置颜色
  }
}

.ratio__bg {
  position: absolute;
  top: 50%;
  left: 50%;
  width: var(--inner);
  height: var(--inner);
  transform: translate(-50%, -50%);
  animation: rotate 3s linear infinite; // 旋转动画
}

.ratio__title {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: var(--font-xs);
  color: var(--white);

  b {
    font-weight: normal;
  }

  em {
    color: var(--orange);
    font-style: normal;
    margin-top: 2px;
  }
}

.ratio__chart {
  width: 100%;
  height: 100%;
}

/* ---------- 旋转动画定义 ---------- */
@keyframes rotate {
  to {
    transform: translate(-50%, -50%) rotate(-360deg);
  }
}
</style>

comp-hub 组件与传统组件的区别

comp-hub 平台上的组件与传统项目中的组件有以下关键区别:

  1. 资源封装方式

    • comp-hub 组件采用自包含设计,所有依赖资源(如图像)都必须包含在组件文件夹内
    • 传统项目通常将静态资源集中存放在项目级别的 assets 目录
  2. 资源引用方式

    • comp-hub 组件必须使用相对路径引用所有资源
    • 传统项目中常使用路径别名(如 @/assets/)简化资源引用
  3. 外部依赖处理

    • comp-hub 组件仅允许引入平台支持的第三方库(如示例中的 echarts)
    • 不允许引入组件文件夹外部的自定义模块或工具函数
  4. 组件独立性

    • comp-hub 组件设计为完全独立的单元,可以在不同项目间无缝移植
    • 传统项目中的组件可能依赖项目特定的全局配置、主题或工具函数

上传业务组件到平台

完成组件开发后,按照组件上传章节中的步骤将业务组件上传到 comp-hub 平台:

  1. 打开 comp-hub 平台并进入「上传组件」页面
  2. 选择您的业务组件文件夹(如本例中的 QinParamRatio
  3. 配置预览选项,选择 demo/index.vue 作为小窗预览文件
  4. 填写组件描述和其他元数据
  5. 点击「上传」按钮完成发布

上传前预览

上传前,您可以在平台上预览组件效果,确保一切正常:

组件上传前预览

最佳实践建议

在开发和上传业务组件时,建议遵循以下最佳实践:

  1. 组件命名:使用有意义的组件名称,可考虑添加前缀以避免命名冲突
  2. 文档完善:提供详细的 README.md 文件,包括组件功能、属性说明和使用示例
  3. 资源优化:优化组件内的图片等资源,确保组件体积合理
  4. 错误处理:添加适当的错误处理逻辑,提高组件的健壮性
  5. 版本管理:遵循语义化版本规范,清晰标记组件版本变更内容

后续步骤

  • 查看预览组件章节,了解如何在平台上预览您上传的业务组件
  • 参考更新组件章节,学习如何维护和更新已发布的组件版本