amis Mapping 映射组件完全指南:从字典映射到自定义模板渲染
2026/9/13 18:41:00 网站建设 项目流程

amis Mapping 映射组件完全指南:从字典映射到自定义模板渲染

【免费下载链接】amis前端低代码框架,通过 JSON 配置就能生成各种页面。项目地址: https://gitcode.com/GitHub_Trending/am/amis

Mapping(映射)是 amis 低代码框架中用于"值 → 展示"转换的核心展示型组件:它将后端返回的编码值(如12happy)映射为友好的标签、HTML 甚至任意 amis 组件,常用于状态字典、枚举翻译、表格列格式化与表单静态展示。本文以 docs/zh-CN/components/mapping.md 为主体,结合 Mapping.tsx 源码与 Mapping.test.tsx 测试用例,系统讲解映射配置、HTML/组件/模板渲染、多值展示、远程字典拉取及 Field 场景集成,读完后可直接在页面、表格与表单中落地完整的映射方案。

基本用法

Mapping 组件通过map属性定义"编码值 → 展示内容"的映射规则,通过value(或数据域中name关联的变量)指定当前要映射的值。最简单的用法如下:

{ "type": "page", "body": { "type": "mapping", "value": "1", "map": { "1": "第一", "2": "第二", "3": "第三", "*": "其他" } } }

这里value: "1"命中map中的"1"键,页面渲染出文本"第一"。值得注意的是,map中的"*"是一个通配键:当 value 未命中任何具体键时,会回退到该键对应的值。这一行为在源码 Mapping.tsx 的renderSingleValue中体现——先精确查表,找不到再取map['*']

如果 value 为空或未命中且没有配置通配键,组件会渲染占位符。从源码的defaultProps可以看到 Mapping.tsx 中默认占位符为'-',默认 map 为{'*': '通配值'}。测试用例 Mapping.test.tsx 也验证了:无值时渲染text-muted样式的-value=1渲染"漂亮",未命中的value=5渲染通配值"其他"。

渲染 HTML

map的 value 不仅可以是纯文本,还可以直接写 HTML 字符串,非常适合做带颜色的状态标签:

{ "type": "page", "body": { "type": "mapping", "value": "2", "map": { "1": "<span class='label label-info'>漂亮</span>", "2": "<span class='label label-success'>开心</span>", "3": "<span class='label label-danger'>惊吓</span>", "4": "<span class='label label-warning'>紧张</span>", "*": "<span class='label label-default'>其他:${type}</span>" } } }

上例中value: "2"会渲染为绿色(success)的"开心"标签。HTML 字符串会被 amis 当作模板渲染,因此${type}这类模板语法同样生效(通配项中其他:${type}会取数据域中的type变量值),这一点从 Mapping.tsx 的return render('tpl', label)可以看出——所有非 itemSchema 的映射值最终都通过 tpl 渲染器输出。测试 Mapping.test.tsx 覆盖了该 HTML 场景的快照。

渲染其它组件

映射值也可以是完整的 amis schema,此时 Mapping 会把该 schema 作为子组件渲染出来。例如按状态渲染成不同颜色的 Tag:

{ "type": "page", "body": { "type": "mapping", "value": "1", "map": { "1": { "type": "tag", "label": "#4096ff", "displayMode": "rounded", "color": "#4096ff" }, "2": { "type": "tpl", "tpl": "2" }, "*": "其他" } } }

这里value: "1"会渲染一个圆角蓝色 Tag,value: "2"渲染一个 tpl 文本。源码中的判定逻辑位于 Mapping.tsx:当映射值是 object 且包含type字段时,判定为 schema,通过render('tpl', label)前先给对象补上name字段后按组件渲染;当映射值是 object 但没有type字段时,则视为纯数据对象,默认取label字段展示。

注意:一旦配置了itemSchema,映射值将不再作为 schema 渲染(详见下一节)。

测试 Mapping.test.tsx 验证了 schema 渲染:value=1时输出与render({type: 'tag', label: '漂亮'})完全一致的 DOM。此外,issue #9613 对应的用例 Mapping.test.tsx 展示了在表格列中嵌套status组件做级联映射的用法,map['*']的值本身又是一个带map/labelMap的 status schema,最终单元格渲染为"处理中"。

渲染自定义模板

该能力自2.5.2版本起提供。

配置itemSchema可以统一控制所有映射值的渲染模板,支持HTML字符串或SchemaNode两种形式。它的渲染入口在 Mapping.tsx:render('mappingItemSchema', itemSchema, {...}),渲染时通过createObject(data, isObject(value) ? value : {item: value})把"映射值"并入数据域——映射值是 object 时其属性可直接用${xxx}取,非 object 时通过${item}获取。

HTML 或字符串模板

itemSchema是字符串时,它作为模板渲染,用${item}获取当前映射值:

{ "type": "page", "body": { "type": "mapping", "value": "1", "map": { "1": "第一", "2": "第二", "3": "第三", "*": "其他" }, "itemSchema": "自定义模板:<span style='color: red'>${item}</span>" } }

SchemaNode 模板

itemSchema也可以是一个 amis schema,此时每条映射值都会套用该 schema 渲染,例如统一渲染成 Tag:

{ "type": "page", "body": { "type": "mapping", "value": "1", "map": { "1": "第一", "2": "第二", "3": "第三", "*": "其他" }, "itemSchema": { "type": "tag", "label": "${item}" } } }

测试 Mapping.test.tsx 验证:value=1时输出内容与独立渲染tag('漂亮')完全一致。

在模板中渲染数据

itemSchema模板内的数据来源遵循三条规则:

  • 映射值是object时,用模板语法${xxx}直接取该对象的属性;
  • 映射值是非object时,用${item}获取映射值本身;
  • 同时还可以访问数据域中的其它变量

示例:映射值为对象、itemSchema为 Tag,同时引用对象属性与页面数据域变量:

{ "type": "page", "data": { "myName": "cat" }, "body": { "type": "mapping", "value": "1", "map": { "1": { "label": "开心", "color": "red" }, "2": { "label": "伤心", "color": "blue" }, "3": { "label": "冷漠", "color": "gray" }, "*": "其他" }, "itemSchema": { "type": "tag", "label": "${myName} ${label}", "color": "${color}" } } }

value: "1"命中的对象是{label: "开心", color: "red"},与页面数据{myName: "cat"}合并后,最终渲染出文本"cat 开心"、红色背景的 Tag。测试 Mapping.test.tsx 展示了普通 map(多 key 对象数组)配合 itemSchema 时,模板可直接引用valueField/labelField命名的字段(如${name} ${text})。

映射展示多个

该能力自1.5.0版本起提供。

value数组时,Mapping 会依次对每个元素做映射并排展示多个结果:

{ "type": "page", "body": { "type": "mapping", "value": ["1", "2", "3", "4", "5"], "map": { "1": "<span class='label label-info'>漂亮</span>", "2": "<span class='label label-success'>开心</span>", "3": "<span class='label label-danger'>惊吓</span>", "4": "<span class='label label-warning'>紧张</span>", "*": "<span class='label label-default'>其他</span>" } } }

这里五个状态标签会被依次渲染出来(其中45均落到通配键"其他")。其实现位于源码的render()方法 Mapping.tsx:当mapKey(由getPropValue解析出的值)为数组时,逐个调用renderSingleValue渲染,每个元素外层包裹map-${index}的 key。

map 映射源

map属性支持两种数据格式:k-v 对象和对象数组(对象数组自2.5.2起支持)。

k-v 对象

最常见的映射表形式,键为待匹配的值,值为展示内容:

{ "type": "mapping", "value": "1", "map": { "1": "第一", "2": "第二", "3": "第三", "*": "其他" } }

对象数组

简单对象数组

每个元素是"单 key"对象,key 为待匹配值:

{ "type": "mapping", "value": "1", "map": [{"1": "第一"}, {"2": "第二"}, {"3": "第三"}, {"*": "其他"}] }

源码setMap中的归一化逻辑 Mapping.tsx 会识别单 key 对象数组并逐一摊平为 k-v 映射;测试 Mapping.test.tsx 验证了该数组格式与 k-v 对象渲染结果一致。

多 key 对象数组

当数组元素包含多个字段时,需要通过valueField指定哪个字段作为匹配value的 key,用labelField指定展示字段(不配置时默认为label):

{ "type": "mapping", "value": "happy", "valueField": "name", "map": [ { "name": "happy", "label": "开心" }, { "name": "sad", "label": "悲伤" }, { "name": "*", "label": "其他" } ] }

也可以让元素携带更多附加字段(如颜色),在 schema 渲染场景下被引用:

{ "type": "page", "body": { "type": "mapping", "value": "happy", "valueField": "name", "labelField": "label", "map": [ { "name": "happy", "label": "开心", "color": "red" }, { "name": "sad", "label": "悲伤", "color": "blue" }, { "name": "*", "label": "其他", "color": "gray" } ] } }

源码中多 key 对象的处理同样在setMap:当对象 keys 数量大于 1 时,使用res[now[self.valueField]] = nowvalueField为键、整个对象为值构建映射。Store 中valueField的默认值为'value'(见 Mapping.tsx)。需要注意:配置labelField后,映射值无法再作为 schema 渲染(此时对象统一取labelField字段展示,见 Mapping.tsx)。另外源码针对 amis-editor 有特殊处理:keys 数量为 2 且包含$$id时,会先过滤掉$$id再按单 key 对象处理。

用作 Field 时

当 Mapping 用在 Table 的列(Column)、List 的内容、Card 卡片内容以及表单的 Static-XXX 中时,可以通过name属性关联数据域中的同名变量进行映射。注意type: 'mapping'type: 'map'等价——注册别名在 Mapping.tsx 的@Renderer({type: 'mapping', alias: ['map']})中定义。

Table 中的列类型

将列type设为mapping并配置namemap,即可对每一行数据做字典翻译:

{ "type": "table", "data": { "items": [ { "id": "1", "type": "1" }, { "id": "2", "type": "2" }, { "id": "3", "type": "3" } ] }, "columns": [ { "name": "id", "label": "Id" }, { "name": "type", "label": "映射", "type": "mapping", "map": { "1": "<span class='label label-info'>漂亮</span>", "2": "<span class='label label-success'>开心</span>", "3": "<span class='label label-danger'>惊吓</span>", "4": "<span class='label label-warning'>紧张</span>", "*": "其他:${type}" } } ] }

List 的内容、Card 卡片的内容配置方式与此相同。另外在 exportExcel.ts 中可以看到,表格导出 Excel 时对mappingstatic-mapping类型会特殊处理,将映射后的展示值写入导出结果。

Form 中静态展示

在表单中使用static-mapping实现只读字典展示(源码兼容层 compat.ts 中'mapping': 'static-mapping'表明表单场景下两者可互通):

{ "type": "form", "data": { "type": "2" }, "body": [ { "type": "static-mapping", "name": "type", "label": "映射", "map": { "1": "<span class='label label-info'>漂亮</span>", "2": "<span class='label label-success'>开心</span>", "3": "<span class='label label-danger'>惊吓</span>", "4": "<span class='label label-warning'>紧张</span>", "*": "其他:${type}" } } ] }

name: "type"使组件从表单数据域读取type变量的值进行映射。

布尔值映射

映射值可以是布尔类型。提供两种写法:

写法一:用"1"表示开、"0"表示关(注意此时 value 为true):

{ "type": "form", "data": { "type": true }, "body": [ { "type": "static-mapping", "name": "type", "label": "映射", "map": { "1": "<span class='label label-info'>开</span>", "0": "<span class='label label-default'>关</span>" } } ] }

写法二:直接用"true"/"false"作为键:

{ "type": "form", "data": { "type": true }, "body": [ { "type": "static-mapping", "name": "type", "label": "映射", "map": { "true": "<span class='label label-info'>开</span>", "false": "<span class='label label-default'>关</span>" } } ] }

两种写法都依赖源码中的布尔兼容逻辑 Mapping.tsx:当key === true且存在map['1']时命中"开",当key === false且存在map['0']时命中"关",否则回退到通配键。

远程拉取字典

该能力自1.1.6版本起提供。

字典数据可能来自后端接口。通过配置source属性即可远程拉取,接口返回字典对象即可,数据格式与map配置一致:

{ "type": "form", "data": { "type": "2" }, "body": [ { "type": "mapping", "name": "type", "label": "映射", "source": "/api/mapping" } ] }

从源码看,source的加载逻辑在 Mapping.tsx 的reload()方法中:normalizeApi将字符串规范化为 API 配置后,通过env.fetcher请求;Store 的load方法 Mapping.tsx 会从响应中依次识别data.optionsdata.itemsdata.records数组,否则将整个data作为字典数据。默认 source 有 30s 缓存(见 Mapping.tsx 的api.cache = api.cache ?? 30 * 1000),通常字典数据不长变更,如需调整缓存策略,参考 API 文档 中缓存相关的配置。

source或接口响应内容变化时,组件会在componentDidUpdate中通过isApiOutdated判断并自动重新拉取(见 Mapping.tsx)。

关联上下文变量

source也支持配置为变量表达式,从当前数据域直接取值作为映射字典:

注意:当数据域里的变量值为$$时,表示将所有接口返回的data字段值整体赋值到对应的 key 中。

{ "type": "form", "initApi": { "url": "/api/mapping", "method": "get", "responseData": { "zidian": "$$$$", "type": "2" } }, "body": [ { "type": "mapping", "name": "type", "label": "映射", "source": "$${zidian}" } ] }

initApi通过responseData将接口返回的data整体赋给变量zidian,Mapping 的source: "$${zidian}"则引用该变量。源码中变量型 source 的处理在 Mapping.tsx:isPureVariable(source)判定后调用resolveVariableAndFilter(source, data, '| raw')解析变量并store.setMap(...)直接设为映射表;componentDidUpdate中还会对比变量前后值,变化时自动更新映射(见 Mapping.tsx)。

占位文本

当数据不存在时,可通过placeholder控制展示内容:

{ "type": "page", "body": { "type": "mapping", "placeholder": "数据不存在", "map": { "1": "第一", "2": "第二", "3": "第三", "*": "其他" } } }

例如value为空字符串、null或 undefined 时,组件会渲染placeholder指定的文本。源码实现中占位文本渲染在 Mapping.tsx,默认值为'-'(见 defaultProps),并以text-muted样式输出,测试用例对此有专门断言(Mapping.test.tsx)。

属性表

属性名类型默认值说明
classNamestring外层 CSS 类名
placeholderstring-占位文本(源码 defaultProps 默认值为-
mapobjectArray<object>映射配置(支持 k-v 对象、简单对象数组、多 key 对象数组)
sourcestringorAPI远程数据源或变量表达式,详见 API 文档 与 数据映射;默认 30s 缓存
valueFieldstringvalue2.5.2起,map 或 source 为Array<object>时,用来匹配映射的字段名(Store 中默认值为'value',见 Mapping.tsx)
labelFieldstringlabel2.5.2起,map 或 source 为Array<object>时,用来展示的字段名;注:配置后映射值无法作为 schema 组件渲染
itemSchemastring或SchemaNode2.5.2自定义渲染模板,支持htmlSchemaNode;当映射值是非object时,可使用${item}获取映射值;当映射值是object时,可使用映射语法${xxx}获取object的值;也可使用数据映射语法${xxx}获取数据域中变量值

小结

Mapping 组件以极简的 JSON 配置覆盖了从基础字典翻译到复杂自定义渲染的完整链路:map支持 k-v 对象与对象数组(valueField/labelField),映射值可以是文本、HTML、任意 amis schema,itemSchema提供统一的模板化渲染;数组 value 支持多值并列展示;source支持远程字典拉取(默认 30s 缓存)与上下文变量引用;在 Table 列、List、Card 与表单static-mapping中通过name即可无缝复用。结合 Mapping.tsx 源码与 Mapping.test.tsx 测试,开发者可以精确掌握其匹配优先级(精确键 → 布尔兼容键 → 通配键)、对象归一化规则与数据域合并机制,在实际项目中灵活构造可维护的枚举展示方案。

【免费下载链接】amis前端低代码框架,通过 JSON 配置就能生成各种页面。项目地址: https://gitcode.com/GitHub_Trending/am/amis

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询