npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

liandong-change-chart

v0.0.3

Published

This is a component

Downloads

5

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

组件从发起查询到渲染经历可概括为三个阶段:

  1. 发起查询
  2. 处理返回数据
  3. 渲染视图

在“处理返回数据”阶段,如果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方法: 调试-样式及主题

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

顶部可切换数据源类型,来调试组件对不同数据的处理逻辑: 调试-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

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