数据交互选项(筛选 / 选中联动 / 动态数据项 / 条件样式 / 属性数据源)
VpElement基类的数据交互能力,多数组件可用;持久化形态写错会导入报错(尤其动态数据项的 JSON 串键)。 返回目录:index.md;全量选项字典(最权威):widget-schema.generated.json。
0. 数据交互选项详解(筛选 / 选中 / 联动 / 动态数据项 / 条件样式)
这些是 VpElement 基类能力(多数组件可用),是"数据交互"类需求的核心。务必按下面的持久化形态写,写错会导入即报错(尤其动态数据项)。每个特性都有对应的可导入示例:见 examples/ 下的 filter.json、selection-passing.json、linkage.json、dynamic-data-item.json、conditional-style.json、secondary-dev-selection.json。
0.1 数据筛选 filter(组件级,先筛后用)
filter:true 开启,再用 row-filter-mode 选模式:
| row-filter-mode | 含义 | 配套参数 |
|---|---|---|
no-condition(默认) |
不筛 | — |
data-row |
只取第 N 行 | row-filter-row-index(从 1 起) |
data-rows |
从第 N 行起取 M 条 | row-filter-start-index(起始,1 起)、row-filter-row-count(条数) |
custom-rules |
条件构建器(内联条件组逐行过滤) | row-filter-rules(二维数组,组间 OR/组内 AND,与 dataRules[].rules 同构) |
data-rule |
满足某工程数据规则的行 | row-row-filter-mode-id = dataRules[].uid(⚠️键名就是这么拗口,不是 row-filter-rule) |
direct-judgment |
直接按「表-字段-运算符-值」判断 | row-filter-source-table("connUid,tableUid")、row-filter-source-field、row-filter-operator(=/>/</!=/>=/<=/⊃/!⊃/∅/!∅)、row-filter-compare-value(∅/!∅ 不需要) |
"options": { "filter": true, "row-filter-mode": "data-rows",
"row-filter-start-index": 2, "row-filter-row-count": 3 }
另有渲染限流 data-row-limit(number,默认 0=不限):组件渲染行数上限,只截断渲染取数、不影响条件样式判断与字段统计,大数据量保护性能用。
0.2 选中传递 selection / 联动 linkage
- 发起方开
select-sync-emit:true(或cross-filter-emit:true);接收方开select-sync-receive:true(或cross-filter-receive:true)。cross-filter 只看接收组件自身开关,页面开关可省。选中传递:basic-table(及map-2d)自带onSelection,自身select-sync-receive即可;图表/列表/排行等其余接收方只实现onSelectItem,要靠父容器(页面或group-panel)开select-sync-receive向子级广播——而页面级开关只在编辑器内预览生效(运行态/view、SDK 页面不初始化watchSelection,见 interactions.md 触发器清单下注),故运行态须把这类接收方包进开了select-sync-receive的group-panel。 - 表格用
select-sync-fields(field,三元组)声明「按哪个字段匹配选中行」;图表按其类目维度(category/category-field)发起。 - 联动广播的键是字段别名,接收侧按「别名 → uid → sourceField」解析回行键;组件取数顺序是先联动过滤、再组件筛选(§0.1)。
- 高级路由(精确控制作用范围,默认广播给所有开接收的组件):
cross-filter-routing-enabled:true+cross-filter-routing——按方向分组,键为cross-filter-emit/cross-filter-receive,每组{ "cross-filter-list-mode": "blacklist"|"whitelist", "cross-filter-widgets": [目标元素引用] }。选中传递同构:select-sync-routing-enabled+select-sync-routing(内层键select-sync-list-mode/select-sync-widgets)。
// 饼图发起
"options": { "select-sync-emit": true, "category": [["conn","tbl","城市"]], "value": [["conn","tbl","数量"]] }
// 表格接收
"options": { "select-sync-receive": true, "select-sync-fields": [["conn","tbl","城市"]], "table-data-fields": [["conn","tbl","城市"]] }
0.3 动态数据项 dynamic-prop-fields(用数据驱动任意样式项)⚠️ 最易错
把某个样式选项(如 opacity)绑到数据字段,数据变样式跟着变。dynamic-prop-entries[].name 与 dynamic-prop-fields 的键都必须是「选项路径数组」的 JSON 字符串(运行时会 JSON.parse(name)):
dynamic-prop-entries:[{ "name": "<JSON路径>", "alias": "显示名" }]dynamic-prop-fields:{ "<JSON路径>": { "dynamic-prop-field": [[connUid,tableUid,fieldUid]] } }<JSON路径>=JSON.stringify(["opacity"])得到的字符串"[\"opacity\"]"(不是裸"opacity"!多段路径同理JSON.stringify(["a","b"]))。
"options": {
"dynamic-prop-entries": [{ "name": "[\"opacity\"]", "alias": "不透明度" }],
"dynamic-prop-fields": { "[\"opacity\"]": { "dynamic-prop-field": [["conn","tbl","不透明度"]] } }
}
裸写
"opacity"会在运行时抛Unexpected token 'o', "opacity" is not valid JSON。opacity、enable两路径在编辑态也即时应用,其它路径运行/预览态才写入。源码:VpElement.watchRelatedFields(JSON.parse(entry.name))、_toRelatedFieldEntry(JSON.stringify([paths]))。
0.4 条件样式 conditionalStyles(满足数据规则→改样式)
写在节点顶层(与 options 平级),不在 options 里。命中工程数据规则就把 value 应用到 paths:
{
"uid": "w_x", "type": "basic-text",
"options": { "text-font": { "size": 64, "color": "#ffffff" } },
"conditionalStyles": [{
"paths": ["text-font"],
"cases": [
{ "ruleId": "dc_alarm", "value": { "size": 64, "color": "#ff4d4f" } },
{ "fallback": true, "value": { "size": 64, "color": "#52c41a" } }
]
}]
}
paths:目标选项路径(字符串数组,直接用,不做 JSON 编码)。cases按顺序求值:ruleId引用dataRules[].uid;或inlineRules(二维规则,形同dataRule.rules);fallback:true兜底。命中即应用其value并停止。- 命中写值走
setTransientOption(不进历史、退预览还原);无命中且无fallback时unsetTransientOption还原基线值。getOption()会合并 transient 层,可直接读回生效值。 - 程序化 API:
element.setConditionalStyle(paths, ruleObj)/unsetConditionalStyle(paths)/getConditionalStyle(paths),求值器element._resolveConditionalStyleValue(ruleObj)返回命中值/兜底/undefined。inlineRules每项是[[{field,func,args}]]组数组(组内 AND、组间 OR);field用字段 uid,connection/table可省(按 field uid 反查所属表)。
二次开发触发选中:按钮内
applySelection({字段:值})/withdrawSelection()属宿主二次开发代码(ExecuteScriptAction经runHostScript委托宿主执行),不在工程 JSON 内。本组件集无「按钮/横向菜单」,工程 JSON 层面用「支持选中传递的中间组件(如饼图)→ 表格 select-sync-fields」等价复现最终效果(见secondary-dev-selection.json)。
0.5 属性数据源 diy-connection(组件属性反向产出连接,供别组件绑定)
编辑器里某属性右侧 ⋮ →「生成属性数据源」即可把该属性(如文本的 text)暴露成一条数据连接,其它组件在「数据」面板的页面公共数据树里就能勾选绑定。产物会真正并入工程 connections / connectionData(数据树可见、可绑、随工程持久化)。一份导入快照需缀合三处(约定:<cUID>=生产方组件 uid(piece 为 ownerWidget.uid-uid);<entry>=该属性选项路径的 JSON 串,如 ["text"];连接 uid 恒为 __vp_prop_<cUID>、表 uid 恒为 <cUID>::<entry>、字段恒为 value):
// ① 生产方节点 options(与「生成」后持久化的一致)
{ "uid": "w_src", "type": "basic-text",
"options": {
"text": "本月主推:新能源汽车",
"prop-source-entries": [
{ "name": "[\"text\"]", "alias": "主推文案", "cUID": "w_src", "connectionUID": "__vp_prop_w_src" }
]
} }
// ② connections 增加一条 prop-source 连接
{ "uid": "__vp_prop_w_src", "name": "属性数据源", "type": "prop-source", "connectorType": "prop-source",
"tables": [{ "uid": "w_src::[\"text\"]", "name": "主推文案", "fields": [{ "uid": "value", "alias": "value", "type": "string" }] }] }
// ③ connectionData 灌入当前值(运行时由生产方 watch 持续回写)
"__vp_prop_w_src": [{ "tableId": "w_src::[\"text\"]", "rows": [{ "value": "本月主推:新能源汽车" }] }]
// 消费方按三元组绑定:文本 value-field / 表格 table-data-fields
"value-field": [["__vp_prop_w_src", "w_src::[\"text\"]", "value"]]
prop-source-entries[].name与表 uid 的<entry>是选项路径数组的 JSON 串(JSON.stringify(["text"])),不是裸字符串。- 编辑器「生成属性数据源」只产出单字段
value(无绑定字段路径);消费方字段 uid 恒为value。 - 源码:
VpElement.addDiyConnectionField/watchDiyConnectionFields/removeDiyConnectionField(产出/监听/移除)+VpScreen.createPropertyConnection/updatePropertyConnectionData/updateDiyData/removePropertyConnection(挂在 Screen 上、委托projectContext;并入工程连接、回写行、移除)。完整示例见examples/property-data-source.json。
VP-TSX 写法(本文特性的映射要点)
映射总规则见 vptsx.md。本文四处易错点在 TSX 里长这样:
// 筛选/选中联动:普通 kebab 属性
<basic-table select-sync-receive={true} select-sync-fields={bind('conn', 'tbl', '城市')} … />
// 动态数据项:键仍是「选项路径数组的 JSON 串」——TSX 里不豁免,照写转义串或用 JSON.stringify
<basic-graphical
dynamic-prop-entries={[{ name: JSON.stringify(['opacity']), alias: '不透明度' }]}
dynamic-prop-fields={{ [JSON.stringify(['opacity'])]: { 'dynamic-prop-field': bind('conn', 'tbl', '不透明度') } }} />
// 条件样式:顶层保留 prop(不进 options),ruleId 命中 defineProject 的 dataRules[].uid
<basic-text conditionalStyles={[{ paths: ['text-font'], cases: [{ ruleId: 'dc_alarm', value: { size: 40, color: '#ff4d4f' } }] }]} … />
// 属性数据源:三处缀合与 JSON 完全同构(prop-source-entries 属性 + connections/connectionData 原始对象)