3、第一个自定义组件:创建基础Widget项目结构、理解widget-config.json、widgets-bundle.js的作用
好,咱们正式开始动手了。
前面两章我们把ThingsBoard的组件体系、开发环境都捋了一遍。说实话,理论讲再多,不如亲手写一个组件来得实在。这一章,我们就来创建第一个自定义组件。
我会带着你一步步搭起项目结构,然后重点讲清楚两个核心文件——widget-config.json和widgets-bundle.js。这两个文件,说白了就是组件的「身份证」和「户口本」。搞懂了它们,后面写任何组件都顺风顺水。
3.1 创建基础Widget项目结构
我个人习惯,每个自定义组件都放在一个独立的文件夹里。这样管理起来清爽,后期维护也方便。
先看看一个最简的组件项目长什么样:
my-first-widget/
├── widget-config.json
├── widget.js
└── widget.css
嗯,就三个文件。别嫌少,麻雀虽小五脏俱全。
- widget-config.json:组件的配置文件。告诉ThingsBoard「我叫什么、长什么样、需要什么数据」。
- widget.js:组件的核心逻辑。渲染、更新、销毁,全在这里。
- widget.css:样式文件。让组件看起来顺眼。
我在项目中遇到过不少新手,一上来就把所有代码塞进一个文件里。结果后面改需求时,找配置找半天,找样式又找半天。所以从一开始就分好文件,这是个好习惯。
3.2 理解widget-config.json
这个文件,是ThingsBoard认识你组件的第一步。它定义了组件的基本信息、数据源要求、以及可配置的参数。
来看一个最简的配置:
{
"alias": "my_first_widget",
"name": "我的第一个组件",
"description": "这是一个演示用的基础组件",
"type": "latest",
"sizeX": 6,
"sizeY": 4,
"resources": [
{
"url": "widget.js"
},
{
"url": "widget.css"
}
],
"settingsSchema": {},
"dataKeySettingsSchema": {},
"defaultConfig": "{}"
}
咱们拆开来看每个字段的作用:
| 字段名 | 说明 | 我的经验 |
|---|---|---|
alias |
组件的唯一标识。只能用字母、数字、下划线。 | 我习惯用项目名做前缀,避免和别人冲突。 |
name |
显示在组件库里的名字。中文英文都行。 | 建议用中文,团队成员一看就懂。 |
type |
组件类型。常用的是latest(最新值)和timeseries(时序数据)。 |
展示单个设备状态用latest,展示历史趋势用timeseries。 |
sizeX/sizeY |
组件在仪表盘上的默认尺寸。单位是网格。 | 别设太大,用户拖进来再调也不迟。 |
resources |
组件依赖的JS和CSS文件列表。 | 顺序很重要,先引CSS再引JS。 |
settingsSchema |
组件设置面板的JSON Schema。留空表示没有设置项。 | 初期可以空着,后面再慢慢加。 |
defaultConfig |
默认配置,JSON字符串格式。 | 至少给个空对象{},避免报错。 |
alias一旦确定,尽量不要修改。因为仪表盘上已经引用的组件实例,是通过alias来关联配置的。改了就找不到了。
你可能会问:「为什么要有settingsSchema和defaultConfig两个东西?」
嗯,这个问题我当初也困惑过。简单说:settingsSchema定义的是「用户能调什么」,而defaultConfig定义的是「初始值是什么」。一个管界面,一个管数据。
3.3 理解widgets-bundle.js的作用
好,现在组件有了。但ThingsBoard怎么知道「哦,我有个新组件可以用了」?
这就轮到widgets-bundle.js出场了。
你可以把它理解成一个「组件清单」。它把所有组件的配置打包在一起,告诉ThingsBoard:「看,这些组件都是我提供的,你注册一下吧。」
一个典型的bundle文件长这样:
self.onInit = function() {
self.registerWidget('my_first_widget', {
widgetConfig: {
alias: 'my_first_widget',
name: '我的第一个组件',
// ... 其他配置
},
widget: function(ctx) {
// 组件的渲染逻辑
}
});
};
等等,这里有个关键点——self.onInit。这个函数在bundle加载时自动执行。你需要在里面调用self.registerWidget来注册每个组件。
我记得第一次写bundle时,忘了加self.onInit,结果组件怎么都加载不出来。查了半天文档才发现这个坑。所以,千万别漏了。
实际项目中,bundle文件通常放在widget-bundles目录下:
my-widget-bundle/
├── widget-bundles/
│ └── my-bundle.js
├── my-first-widget/
│ ├── widget-config.json
│ ├── widget.js
│ └── widget.css
└── my-second-widget/
├── widget-config.json
├── widget.js
└── widget.css
这样组织的好处是:一个bundle可以包含多个组件。你想想看,如果你有十几个组件,每个都单独注册,那管理起来多麻烦。用一个bundle统一管理,清爽多了。
widget-config.json是组件的「身份证」——描述组件自身信息。widgets-bundle.js是组件的「户口本」——告诉系统有哪些组件可用。- 一个bundle可以注册多个组件,方便统一管理。
3.4 实战:把组件跑起来
光说不练假把式。我们来走一遍完整的流程。
第一步: 在ThingsBoard的「自定义组件」页面,上传你的bundle文件。
第二步: 系统会自动解析bundle里的所有组件配置。如果widget-config.json有语法错误,这里就会报错。
第三步: 进入仪表盘编辑模式,在组件库的「自定义」分类下,就能找到你的组件了。
我曾经遇到过一个情况:组件上传成功了,但在仪表盘里死活找不到。后来发现是alias写了个中文,系统不认。所以记住,alias只能用英文和数字。
3.5 本章小结
这一章我们做了三件事:
- 创建了组件的基础项目结构——三个文件,各司其职。
- 吃透了
widget-config.json——组件的身份证,告诉系统「我是谁」。 - 理解了
widgets-bundle.js——组件的户口本,告诉系统「我有哪些组件」。
下一章,我们会真正开始写组件的渲染逻辑。到时候,你会看到数据是怎么从ThingsBoard流到你的组件里的。嗯,那才是真正好玩的部分。
公众号:蓝海资料掘金营,微信deep3321