ECharts 完整集成
从注入 echarts 到让用户在属性面板配
chartType / xAxis / series的完整链路。
1. 宿主注入
ts
import * as echarts from 'echarts'
import { createHyperCard } from '@hy-bricks/core'
app.use(createHyperCard({
libs: { echarts },
}))详细 libs 注入:/guide/quick-start。
2. 组件源码完整三栏
HTML:
html
<div ref="el" style="width:100%; height:100%"></div>JS:
js
export default {
name: { value: 'MyECharts', CN: 'ECharts 图表' },
attribute: {
chartType: '图表类型 line/bar/pie',
title: '标题',
xAxisData: 'x 轴数据(逗号分隔)',
},
custom: {
seriesData: {
label: '系列数据',
dataInput: true, // ★ 可被 binding 灌入
value: [],
},
},
data() {
return { chart: null }
},
methods: {
mounted() {
const echarts = __HYPERCARD__.libs.echarts
this.chart = echarts.init(this.$refs.el)
this.applyOption()
// 监听 attribute 变化
this.$watch(() => this.chartType, () => this.applyOption())
this.$watch(() => this.title, () => this.applyOption())
this.$watch(() => this.xAxisData, () => this.applyOption())
// 监听 custom.seriesData(binding 灌入)
this.$watch(() => this.custom.seriesData.value, () => this.applyOption())
// resize
this._resizeObs = new ResizeObserver(() => this.chart?.resize())
this._resizeObs.observe(this.$refs.el)
},
beforeUnmount() {
this._resizeObs?.disconnect()
this.chart?.dispose()
},
applyOption() {
const xData = (this.xAxisData ?? '').split(',').map(s => s.trim())
this.chart?.setOption({
title: { text: this.title ?? '' },
xAxis: { type: 'category', data: xData },
yAxis: { type: 'value' },
series: [{
type: this.chartType ?? 'line',
data: this.custom.seriesData.value,
}],
})
},
},
}CSS:
css
.root { width: 100%; height: 100%; }3. 用户在画布看到什么
Step 1:拖入组件
用户从 palette 拖 "ECharts 图表" 到画布,SDK addInstance 创建实例,默认布局 fill。
Step 2:属性面板出现 4 项
宿主属性面板按 attribute + custom 渲染表单:
基础属性
├─ chartType [line ▼]
├─ title [我的图表]
├─ xAxisData [一月,二月,三月]
└─ seriesData(数据源) [绑定...] ← custom.dataInput=true 显示绑定按钮Step 3:用户改 chartType
属性面板 select 切到 bar → instance.props.chartType = 'bar' → Vue reactivity → $watch 触发 → applyOption() 重画。
Step 4:用户绑数据源
点 seriesData(数据源) → 选择已注册 dataSource → 写 PageDocument.bindings:
ts
{
id: 'b1',
source: { kind: 'dataSource', sourceId: 'sales-2024' },
target: { kind: 'instanceDataInput', instanceId: '<chart-id>', key: 'seriesData' },
}运行时 SDK wire binding → fetch dataSource → setDataInput('seriesData', data) → 组件 $watch 触发 → 重画。
4. 完整 DataAdapter 接入
ts
import type { DataAdapter } from '@hy-bricks/canvas'
const dataAdapter: DataAdapter = {
async query({ sourceId, params }) {
const data = await fetch(`/api/data/${sourceId}`).then(r => r.json())
return { status: 'ok', data }
},
subscribe() { return () => {} },
}
<HyperCardPageRenderer
:payload="payload"
:adapters="{ data: dataAdapter }"
canvas-id="dashboard"
/>5. 常见坑
| 现象 | 原因 |
|---|---|
| 组件挂载但 echarts 没出 | .root 没 width:100%; height:100%,echarts canvas 0×0 |
| 改 attribute 组件不响应 | 没在 mounted 里 $watch 那个字段 |
| binding 灌不进 | custom.seriesData.dataInput: true 没声明 → console.warn + no-op |
| 切窗口大小 echarts 没 resize | 没用 ResizeObserver / chart.resize() |
浏览器 console 报 echarts is undefined | 宿主没 createHyperCard({ libs: { echarts } }) |