liandong-change-chart-trigger
v0.0.2
Published
This is a component
Downloads
4
Readme
一、模板目录结构
|--assets
|--icon
|--avatar.png // 展示在组件库列表时使用的图片
|--dist // 打包后的组件包,运行gvp build后可看到
|--node_modules
|--.babelrc
|--config.json // 组件静态配置(不可删除)
|--index.js // 组件入口文件
|--index.scss // 组件样式
|--package.json // 组件包信息
|--postcss.config.js
|--README.md // 组件说明文档
二、起步
项目初始化完成后,包含了一个基础的文本组件demo示例。在组件根目录下,执行以下命令,即可在浏览器启动本地服务:
ty serve
启动后,可在浏览器看到如下界面,左侧是组件能够配置的选项,右侧是文本组件demo的效果预览。调整组件的配置,右侧预览会同步更新,所见即所得:
页面左上角可切换到数据编辑,选择不同类型的数据源。文本组件默认使用静态数据源,可在左侧编辑静态数据,也可通过下拉菜单选择api数据源,效果如下:
页面右上角的调色盘可以切换当前页面的主题,组件的样式可跟随主题变化,切换到黑色主题后,文本组件的边框颜色发生变化,效果如下:
三、开发一个组件
模板中的index.js是组件唯一的入口文件,无论是启动本地服务还是组件打包,都会读取此文件,因此开发者需要在index.js导出组件的全部内容。index.js结构如下:
// 导入组件静态配置(必须)
import cfg from './config.json';
// 导入样式
import './index.scss';
// 组件视图(必须)
class Component {}
// 挂载组件类到静态配置上
cfg.factory = Component;
// 导出组件
export const widget = cfg;
组件由两部分内容构成,二者为必须,缺一不可:
- 静态配置
- 组件视图
在系统中新建一个组件时,会创建一个组件实例,组件实例会从静态配置中获取默认的数据源配置及样式配置,并clone一份保存到组件实例中。在渲染阶段会创建组件视图的实例,并调用实例的render方法完成组件的渲染过程
3.1 静态配置
组件静态配置包括:基础配置、数据源配置、样式配置、样式编辑界面配置
模板中的config.json文件包含了组件的所有静态配置,其结构如下:
{
/* 基础配置 */
"protocol": "1.0.0", // 协议版本,目前只有1.0.0
"alias": "widget", // 组件别名
"category": "single", // 组件类别,目前只有single
/* 数据源配置 */
"data": {},
/* 样式配置 */
"option": {},
/* 样式编辑界面配置 */
"configure": {}
}
3.1.1 数据源配置
数据源配置的结构如下:
{
/* 数据源配置 */
"data": {
/*
* 默认使用的数据源类型(必须),
* 仅支持三种
* default:系统数据源
* api:外部api数据源
* static:静态数据源
*/
"type": "static",
/* gvp数据源配置 */
"default": {},
/* 外部api数据源配置 */
"api": {},
/* 静态数据源配置 */
"static": {}
}
}
组件可以选择使用不同类型的数据源,但必须指定默认使用的数据源,目前支持三种:
1. 系统数据源
系统数据源配置项如下:
{
"data": {
"type": "default",
"default": {
"disabled": false // 是否禁用
"exportData": true // 是否支持导出数据
}
}
}
disable属性用于控制组件数据编辑时,数据源类型下拉菜单选项是否可用。exportData为数据导出设置,若设置true则在系统的仪表盘页面,此类组件则具备导出excel数据功能
2. 外部api数据源
外部api数据源配置项如下:
{
"data": {
"type": "api",
"api": {
"disabled": true, // 是否禁用
"url": "",
"method": "",
"headers": {},
"params": {},
"data": {},
"config": [{ // api请求界面配置
"key": 'url',
"label": 'api地址'
}, {
"key": 'headers',
"label": '请求头信息'
"children": [{
"key": "X-AgileBI-PublishId",
"label": "PublishId"
}]
}]
}
}
}
在创建组件实例时,部分选项会开放出来给用户配置,这些配置项会保存到实例中。对于api数据源,除了http请求的基础配置以外,config属性用于描述开放给用户的api配置,与数据编辑页面api数据的配置界面相对应,开放出来后用户可在数据编辑页面修改组件的api请求配置。
- 每个组件实例都会保存自己的api请求配置,因此“修改”是指修改组件实例,不是静态配置
- children属性只支持一层嵌套
3. 静态数据源
静态数据源配置项如下:
{
"data": {
"type": "static",
"static": {
"data": [{ // 静态数据,渲染时会传递给组件,可自定义
"text": "Hello world"
}]
}
}
}
data为必须属性,定义了组件默认使用的静态数据。在数据编辑中,用户可以修改组件实例使用的静态数据,此数据在渲染阶段会传递给视图层的组件实例,在实例render方法中可以拿到此数据并做渲染逻辑
3.1.2 样式配置
option定义了组件默认的样式配置,配置中可以写任意的json格式数据。以demo中的文本组件为例,结构如下:
{
"option": {
"show": true,
"textStyle": {
"fontSize": 12,
"fontFamily": "Mircrosoft Yahei",
"fontStyle": "normal",
"color": "#5ec264"
},
"title": "dom title attribute"
}
}
在创建组件时,会clone一份默认样式并保存在组件实例中。在渲染阶段,组件的样式也会传递给视图层组件实例,用于在实例render方法中做渲染
3.1.3 样式编辑界面配置
此项配置会应用于组件的样式编辑界面,决定了组件有哪些样式允许用户修改,为用户提供样式个性化配置的入口。
界面配置的嵌套结构要与option的嵌套结构保持一致,以demo中的文本组件为例,配置如下:
{
"configure": {
"show": {
"name": "显示文本",
"type": "boolean",
"default": true
},
"title": {
"name": "悬浮提示",
"type": "text",
"default": ""
},
"textStyle": {
"name": "文本设置",
"type": "group",
"children": {
"fontSize": {
"name": "字体大小",
"type": "number",
"default": 12,
"min": 1,
"max": 30,
"suffix": "px"
},
"fontFamily": {
"name": "文本字体",
"type": "select",
"default": "Microsoft Yahei",
"options": [{
"label": "Times New Roman",
"value": "Times New Roman"
}, {
"label": "宋体",
"value": "SimSun"
}, {
"label": "微软雅黑",
"value": "Microsoft Yahei"
}]
},
"fontStyle": {
"name": "字体风格",
"type": "radio",
"default": "normal",
"options": [{
"label": "普通",
"value": "normal"
}, {
"label": "斜体",
"value": "oblique"
}]
},
"color": {
"name": "字体颜色",
"type": "color",
"default": "#5ec264"
}
}
}
}
}
每一个具体的选项都会使用一个UI组件,对应的基础配置如下:
{
"name": "字体颜色", // 选项名称
"type": "color", // 选项使用的UI组件类型(必须)
"default": "#5ec264" // 选项默认值
// UI组件的其他属性
// ......
}
目前UI组件包括:
1. group
使用group组件时在嵌套层级上,要与option的嵌套层级保持一致
{
"textStyle": {
"name": "文本设置", // 选项名称
"type": "group", // 组件类型(必须)
"children": {} // 组内属性(没有可不填)
}
}
2. boolean
boolean类型组件绑定到选项的值只有true或false
{
"name": "显示文本", // 选项名称
"type": "boolean", // 组件类型(必须)
"default": true // 选项默认值
}
3. color
color类型组件支持hex和rgb颜色格式,如果alpha设置为true(开启不透明度),则颜色格式为rgba
{
"name": "字体颜色", // 选项名称
"type": "color", // 组件类型(必须)
"default": "#5ec264" // 选项默认值
"alpha": true // 是否开启不透明度,默认开启
}
4. number
{
"name": "字体大小", // 选项名称
"type": "number", // 组件类型(必须)
"default": 12 // 选项默认值
"min": 1, // 最小值,默认为0
"max": 30, // 最大值,默认为100
"suffix": "px" // 后缀(可不填)
}
5. radio
{
"name": "字体风格", // 选项名称
"type": "radio", // 组件类型(必须)
"default": "normal", // 选项默认值
"options": [{ // radio选项
"label": "普通", // radio选项显示的名称
"value": "normal" // radio选项的值
}, {
"label": "斜体",
"value": "oblique"
}]
}
6. select
{
"name": "文本字体", // 选项名称
"type": "select", // 组件类型(必须)
"default": "Microsoft Yahei", // 选项默认值
"options": [{ // 下拉菜单选项
"label": "Times New Roman", // 下拉菜单选项显示的名称
"value": "Times New Roman" // 下拉菜单选项的值
}, {
"label": "宋体",
"value": "SimSun"
}, {
"label": "微软雅黑",
"value": "Microsoft Yahei"
}]
}
7. text
{
"name": "悬浮提示", // 选项名称
"type": "text", // 组件类型(必须)
"default": "" // 选项默认值
}
8. textarea
{
"name": "悬浮提示", // 选项名称
"type": "text", // 组件类型(必须)
"default": "" // 选项默认值
"rows": 2 // 文本框行数,默认为2
}
3.2 组件视图
3.2.1 Component类
组件视图层的逻辑定义在index.js的Component类中,其中render方法和destroy方法需要自己实现,render方法要求是幂等的,即对于给定的输入,无论调用多少次,都能够得到相同的渲染结果。Component类的定义如下:
class Component {
/**
* Creates an instance of Component.
* @param {String} id 组件id
* @param {HTMLElement} container 组件容器
* @memberof Component
*/
constructor(id, container) {
this.config = {
theme: {}
};
this.id = id;
this.container = container;
this.chart = null;
this._data = null;
}
/**
* 默认的组件数据处理逻辑
* @static
* @param {Array} data 组件接收的数据
* @param {String} type 组件数据源类型
* @returns {Array}
* @memberof Component
*/
static processData(data, type) {
return data;
}
/**
* 组件初始化方法
* @memberof Component
*/
init() {}
/**
* 设置组件主题
* @param {Object} theme: { name: 'String' }
* 目前有:theme-default\theme-dark\theme-red\theme-blue
* @memberof Component
*/
setTheme(theme) {}
/**
* 渲染组件(必须)
* @param {Array} data 组件数据
* @param {Object} option 组件样式配置
* @param {Object} 暴露给外部组件的系统api
* @memberof Component
*/
render(data, option, api) {}
/**
* 发布组件状态(联动、下钻、跳转)
* @memberof Component
* @return { name: string, value: string } name为状态名称(仅支持'default'),value为状态值
*/
emit() {}
/**
* 组件容器大小变化时的回调
* @memberof Component
*/
resize() {}
/**
* 容器销毁之前,销毁组件实例的方法(必须)
* @memberof Component
*/
destroy() {}
}
3.2.2 数据处理
组件从发起查询到渲染经历可概括为三个阶段:
- 发起查询
- 处理返回数据
- 渲染视图
在“处理返回数据”阶段,如果Component类中声明了静态方法processData,则会调用此方法对返回数据进行处理,处理结果会应用于渲染过程,在render方法中接收此结果。如果对返回数据不需要做任何处理,可以删除此方法,或者直接返回data
对于系统内置的数据源,返回的数据有固定的结构。举例说明,配置一个维度字段“省份”、一个分类字段“产品类别”、一个指标字段“利润”,产品类别字段下有三个分类:技术、家具、办公用品,表格结构如下:
| 省份 | 利润(技术)| 利润(家具)| 利润(办公用品)| | -----| ----------- | ----------- | --------------- | | 安徽 | 60799.48 | 44779.21 | 43450.12 | | 北京 | 25280.5 | 42062.58 | 24618.86 | | 广东 | 119614.6 | 122676.336 | 97420.26 | | ... | ... | ... | ... |
返回数据的结构如下:
[{
columns: [
{ columns: ['dimensionKey'], isDimension: true },
{ columns: ['metricKey', '技术'], isDimension: false },
{ columns: ['metricKey', '家具'], isDimension: false },
{ columns: ['metricKey', '办公用品'], isDimension: false }
],
data: [
['安徽', 60799.48, 44779.21, 43450.12],
['北京', 25280.5, 42062.58, 24618.86],
['广东', 119614.6, 122676.336, 97420.26],
// ...
]
}]
3.2.3 渲染
render方法接收三个参数,其中第三个参数api
暴露给外部组件一些方法,用于获取系统内部的字段信息或状态,其结构如下:
{
field: {
// 获取当前下钻层级,维度、分类、指标字段信息
getFields: () => FieldConfig,
// 获取所有层级的维度、分类、指标字段信息
getAllFields: () => Array<FieldConfig>
},
state: {
// 获取当前的交互状态,stateName支持linkage(联动)、drilldown(下钻)
getState: stateName => { [string]: LinkageState|DrilldownState }
}
}
interface FieldConfig {
dimensions: Array<Field> // 维度字段
categories: Array<Field> // 分类字段
metrics: Array<Field> // 指标字段
}
interface Field {
key: string, // 字段的key
name: string, // 字段名称
aggregator: string, // 字段配置的聚合函数
precision: string, // 字段的精度,仅日期字段使用
aliasName: string, // 字段别名
dataType: number, // 字段类型 0:数值 1:字符 2:日期 3:布尔
}
interface LinkageState {
fields: Array<{ key: string, value: string|number }> // 触发联动时,各字段的key及对应的值
settingIdx: number // 触发联动时,图表的下钻层级
}
interface DrilldownState {
fields: Array<{ key: string, value: string|number }> // 触发下钻时,下钻维度字段的key及对应的值
}
3.3 组件交互
系统内部支持联动、下钻、跳转交互,若想使用系统内部的交互逻辑,可通过调用emit方法实现,此方法用于向系统发布一个交互状态,方法需要返回一个对象,结构如下:
{
name: string, // 交互名称,仅支持'default',表示使用系统内部默认的联动、下钻、跳转交互逻辑流程
value: [{ // 状态值
key: string, // 字段的key
value: string|number // 字段对应的值
}],
param: {} // 额外的参数,目前仅下钻回退会使用,留作日后扩展
}
这里需要注意以下两点:
- 只有当组件使用的数据表是系统内置的数据源时,才能触发系统内部的交互,因为联动、下钻、跳转功能,均是基于内置数据源配置的图表字段而实现
- 交互名称必须要显式的写明 name: 'default',通常情况下default足够使用,系统内已将联动、下钻、跳转的逻辑集成好
以柱状图发起联动为例,横轴为省份(维度),纵轴为访问量(指标),期望通过点击柱状图的某一根柱子发起联动,那么调用emit方法返回值为:
{
name: 'default',
value: [{
key: 'province', // 维度字段’省份‘的key
value: '北京' // 被点击的柱子对应的维度字段‘省份’的值
}]
}
如果维度、分类字段有多个,则可以在value数组中写入多个字段的key及value
在下钻交互中,可能不想通过container中点击footer路径来做回退,这里提供通过emit的下钻回退实现方案:
{
name: 'drilldown',
value: {
index: number // 回退的目标层级
},
param: {
action: 'backward'
}
}
3.4 导出组件
组件最终要从index.js中导出,导出内容为一个对象,里面包含了静态配置及组件视图类
// 挂载组件类到静态配置上
cfg.factory = Component;
// 导出组件
export const widget = cfg;
3.5 工程化
index.js文件结尾有以下代码:
if(module.hot) {
module.hot.accept()
}
这段代码用于开发环境下做热更新,对发布的组件包没有影响,不要删除
另外开发者可直接使用es6语法进行开发,同时也可修改babel配置及postcss配置,并在package.json中自行引入相关的插件依赖,自定义核心代码及样式文件的工程化过程
四、调试
开发完成后,可通过ty serve
命令启动本地服务,在浏览器的控制台中进行调试
在样式编辑页面的右上角,点击调色盘可切换主题,用于调试setTheme方法:
进入数据编辑后,可编辑静态数据的内容,并在右侧刷新预览:
顶部可切换数据源类型,来调试组件对不同数据的处理逻辑:
五、发布
5.1 组件包
发布之前需要修改package.json中的组件名称及版本号,并将组件打包生成dist目录
// package.json
{
"name": "widget", // 组件名称
"version": "1.0.0", // 版本号
"scripts": {
"upload": "npm publish && ty generate && ty sync"
},
"dependencies": {},
"devDependencies": {},
"description": "This is a component"
}
在组件包根目录执行命令,打包成功后会在根目录下生成dist文件夹:
ty build
组件必须要打包后才能发布
5.2 发布组件
在package.json中集成了发布命令upload
,在组件包根目录执行命令即可完成发布:
npm run upload
更详细的发布流程可参考组件发布