0.0.2 • Published 4 years ago

liandong-change-chart-trigger v0.0.2

Weekly downloads
9
License
-
Repository
-
Last release
4 years ago

一、模板目录结构

|--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 数据处理

组件从发起查询到渲染经历可概括为三个阶段: 1. 发起查询 2. 处理返回数据 3. 渲染视图

在“处理返回数据”阶段,如果Component类中声明了静态方法processData,则会调用此方法对返回数据进行处理,处理结果会应用于渲染过程,在render方法中接收此结果。如果对返回数据不需要做任何处理,可以删除此方法,或者直接返回data

对于系统内置的数据源,返回的数据有固定的结构。举例说明,配置一个维度字段“省份”、一个分类字段“产品类别”、一个指标字段“利润”,产品类别字段下有三个分类:技术、家具、办公用品,表格结构如下:

省份利润(技术)利润(家具)利润(办公用品)
安徽60799.4844779.2143450.12
北京25280.542062.5824618.86
广东119614.6122676.33697420.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方法: 调试-样式及主题

进入数据编辑后,可编辑静态数据的内容,并在右侧刷新预览: 调试-静态数据

顶部可切换数据源类型,来调试组件对不同数据的处理逻辑: 调试-api数据

五、发布

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

更详细的发布流程可参考组件发布