占位组件(Placeholder / ButtonPlaceholder)
占位组件(占位符)是视图移动端渲染模板中的占位元素,本身不承载内容,运行时由视图的字段或行按钮按占位序号填充渲染。
概述
占位组件只在「视图移动端渲染」(MetaPageTemplateCategory.MetaView)模板的组件面板中提供,用于自定义移动端卡片的布局结构:
- 字段占位符(字段占位符 /
Placeholder{n},序号 1–30):由视图列表字段绑定,展示字段值。 - 按钮占位符(按钮占位符 /
ButtonPlaceholder{n},序号 31–40):由视图列表行按钮绑定,展示操作按钮。 - 每个占位序号在同一布局中只能使用一次(单例),运行时按序号扫描替换,两类占位组件的底层渲染逻辑统一。
- 未绑定任何内容的占位符在渲染时不占用任何空间(返回空),其所在布局容器若因此无内容也会一并隐藏。
占位符类型
| 界面名称 | widgetType 取值 | 序号范围 | 绑定来源 | 绑定配置位置 |
|---|---|---|---|---|
| 字段占位符 #1 ~ #30 | Placeholder1 ~ Placeholder30 | 1–30 | 视图列表字段(MetaViewListItem) | 字段设置的「移动端占位符绑定」 |
| 按钮占位符 #31 ~ #40 | ButtonPlaceholder31 ~ ButtonPlaceholder40 | 31–40 | 视图列表行按钮(MetaViewListButtonItem) | 行按钮设置的「移动端占位符绑定」 |
绑定取值约束
- 字段的「移动端占位符绑定」下拉仅提供 1–30(字段占位符)。
- 行按钮的「移动端占位符绑定」下拉仅提供 31–40(按钮占位符);历史数据中绑定 1–20 的值仍可正常显示与生效,一旦调整为新值则只能选 31–40。
配置项
占位组件在布局编辑器右侧属性面板中的配置项:
| 配置项 | 说明 |
|---|---|
| 自定义容器样 式 | 应用于占位符容器盒子上的 CSS 样式(如背景、边框、内边距),仅对容器生效 |
| 自定义元素样式 | 透传到占位符内实际渲染的字段/按钮元素上的 CSS 样式(如字号、颜色、字重),不影响容器本身 |
两类样式均输入标准 CSS 样式字符串,支持带或不带花括号(如 { font-size: 16px; })、kebab-case 属性名(如 font-size)、注释与多行格式。
样式应用机制
| 样式配置 | 存储键 | 应用位置 | 作用对象 |
|---|---|---|---|
| 自定义容器样式 | CustomStyle | 占位符 Widget 的 Viewer 渲染层,额外套一层 div | 占位符容器盒子 |
| 自定义元素样式 | ElementStyle | 构建占位内容时透传 | 实际渲染的字段(外层包裹 span)或按钮(直接合并进按钮 style) |
两层样式为叠加关系:容器样式管理占位盒子的外观,元素样式管理内容元素本身。
使用场景
- 移动端卡片排版:将字段按模板布局排布,替代默认的「字段名:字段值」顺序罗列。
- 行按钮自定义位置:把操作按钮放到卡片中任意占位位置。
- 样式微调:通过元素样式调整某个字段/按钮的字号 、颜色,通过容器样式调整占位区域的背景与间距。
下一步
属性明细
以下内容面向技术实现与 AI 检索。
占位符 Widget 属性表
| 属性名 | 类型 | 含义 | 取值/存储值 |
|---|---|---|---|
widgetType | string | 占位符类型标识 | 字段:Placeholder1 ~ Placeholder30;按钮:ButtonPlaceholder31 ~ ButtonPlaceholder40 |
uid | string | 固定唯一标识,用于单例判重 | 字段:placeholder-widget-{n};按钮:buttonplaceholder-widget-{n} |
dragType / originalType | string | 拖拽分类 | Widget |
meta.CustomStyle | string | 自定义容器样式 | CSS 样式字符串,可空 |
meta.ElementStyle | string | 自定义元素样式 | CSS 样式字符串,可空 |
meta 中的键均为字符串化存储(CSS 文本原样保存),渲染时解析为 React 样式对象(kebab-case 转驼峰)。
绑定属性
| 属性名 | 所属实体 | 类型 | 含义 | 取值/存储值 |
|---|---|---|---|---|
MobilePlaceholderIndex | MetaViewListItem | int? | 字段绑定的占位符序号 | 1–30,未绑定为 null |
MobilePlaceholderIndex | MetaViewListButtonItem | int? | 行按钮绑定的占位符序号 | 新绑定 31–40;历史数据可能为 1–20,未绑定为 null |
渲染与替换逻辑
- 运行时按
MobilePlaceholderIndex构建占位内容映射(字段值组件 + 行按钮组件),布局渲染器对Placeholder{n}/ButtonPlaceholder{n}统一按序号扫描替换。 - 布局容器(如基础容器)渲染子节点前会检查占位符是否有对应内容,无内容的占位符不渲染;递归判定后容器若无任何可见子节点也整体不渲染。
- 单 例约束:每个占位序号在布局中只能出现一次,侧边栏按
uid判重隐藏已使用的占位符。
异常与校验
| 场景 | 行为 |
|---|---|
| 复制占位符本身 | 复制操作被拒绝(duplicateItem 返回空),UI 上复制按钮隐藏 |
| 复制包含占位符的容器(任意深度) | 整个复制操作被拒绝,避免复制出重复占位符 |
| 序号重复(历史脏数据) | 渲染时按序号匹配,重复序号的占位符会渲染相同内容 |
| 按钮绑定历史序号 1–20 | 保持兼容,只要不重新调整即继续生效 |
存储示例
占位组件作为节点保存在模板的 Layout 组件树中(数据表 system_metapagetemplate),以下示例为一个包含字段占位符与按钮占位符的完整嵌套结构:
[
{
"id": "3f9c...",
"uid": "7b9a905e-83d4-452b-83c8-694a3e0935e3",
"dragType": "Row",
"originalType": "Row",
"widgetType": "Row",
"widgetTypeName": "基础容器",
"children": [
{
"id": "a1b2...",
"uid": "placeholder-widget-3",
"dragType": "Widget",
"originalType": "Widget",
"widgetType": "Placeholder3",
"widgetTypeName": "字段占位符 #3",
"children": [],
"meta": {
"CustomStyle": "background: #fafafa; padding: 4px 8px;",
"ElementStyle": "font-size: 14px; color: #1890ff;"
}
},
{
"id": "c3d4...",
"uid": "buttonplaceholder-widget-31",
"dragType": "Widget",
"originalType": "Widget",
"widgetType": "ButtonPlaceholder31",
"widgetTypeName": "按钮占位符 #31",
"children": [],
"meta": {
"ElementStyle": "margin-right: 12px;"
}
}
]
}
]
相关实现
| 内容 | 位置 |
|---|---|
| 占位 Widget 定义(编辑器 / 查看器 / 设置面板 / 样式解析) | web/src/components/Widgets/PlaceholderWidgets/PlaceholderWidgets.tsx |
| 占位符类型枚举与序号工具函数 | web/src/components/Widgets/WidgetType.tsx |
| Widget 类型到实例的映射 | web/src/components/Widgets/WidgetSelector.tsx |
| 组件面板分组(字段占位 / 按钮占位) | web/src/components/Widgets/WidgetSidebarItemConfig.tsx |
| 占位内容构建与元素样式透传 | web/src/components/PageCmps/MetaView/MetaViewMobileItem.tsx |
| 单例复制守卫 | web/src/components/Widgets/Basic/layoutTreeHelper.ts(containsSingleUseWidget / duplicateItem) |