amis Each 循环渲染器怎么遍历数组并处理对象数组与嵌套循环
2026/9/14 16:07:51 网站建设 项目流程

amis Each 循环渲染器怎么遍历数组并处理对象数组与嵌套循环

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

在 amis 中,页面内容由 JSON schema 描述。当数据是数组、需要"每个元素生成一个子渲染器"时,用each组件完成:遍历简单数组、遍历对象数组并输出字段、两层嵌套循环,都能用同一套name+items的配置写出来。本文按这三个任务展开,每一步都给出可直接使用的 schema 和判断渲染是否正确的依据。

核心配置来自 Each 循环渲染器文档,先记住属性表中与遍历直接相关的几项:

属性名类型说明
namestring获取数据域中变量,指定要循环的数组
sourcestring获取数据域中变量,支持数据映射
itemsobject使用value中的数据,循环输出渲染器
placeholderstringvalue值不存在或为空数组时的占位文本
itemKeyNamestring获取循环当前数组成员,默认item
indexKeyNamestring获取循环当前索引,默认index

name的优先级比source高(文档原文)。items里模板字符串中的${xxx}是 amis 的数据映射语法,用于从当前数据链取变量值,语法说明见数据映射文档。

遍历简单数组

name指向一个数组变量,items写单个元素的渲染器。每次循环时,item变量拿到当前元素:

{ "type": "page", "data": { "arr": ["A", "B", "C"] }, "body": { "type": "each", "name": "arr", "items": { "type": "tpl", "tpl": "<span class='label label-default m-l-sm'>${item}</span> " } } }

上面的 JSON 即文档中的完整示例(each.md 的"基本用法"),渲染结果是三个标签ABC。判断是否生效:页面中出现 3 个由items生成的节点,数量与数组长度一致。

如果不想依赖同名变量,也可以用source显式引用数据域变量:

{ "type": "each", "source": "${arr}", "items": { "type": "tpl", "tpl": "<span class='label label-default m-l-sm'>${item}</span> " } }

source支持数据映射,取值方式与数据映射中的${xxx}一致。

处理对象数组

数组成员是对象时,有两种取值方式:

  • 直接用内部变量名,如${name},等价于取当前成员对象上的name字段;
  • 通过item.name这种方式显式指定;
  • index获取当前元素的数组索引。
{ "type": "page", "data": { "arr": [{"name": "a"}, {"name": "b"}, {"name": "c"}] }, "body": { "type": "each", "name": "arr", "items": { "type": "tpl", "tpl": "<span class='label label-default m-l-sm'>${name}:${index}</span> " } } }

文档示例的展示结果是a:0b:1c:2这样的标签(示例结果,按示例数据推断)。

文档中有一条明确提醒:如果成员对象本身也有名为index的字段,会覆盖循环索引变量,导致取不到真正的索引。此时改用下一节的itemKeyName/indexKeyName自定义字段名来规避。

嵌套循环:用 itemKeyName 和 indexKeyName 取上层数据

官方文档说明:存在嵌套使用时,默认的item或者index始终拿的是最里面那层的信息;要获取上层each的信息,需要自定义itemKeyNameindexKeyName指定字段名。

以文档"循环嵌套"示例为例,外层数组每个成员带有subList,外层循环把item/index分别改名为itemOutter/indexOutter,内层循环仍用默认名:

{ "type": "each", "name": "arr", "itemKeyName": "itemOutter", "indexKeyName": "indexOutter", "items": [ { "type": "tpl", "inline": false, "tpl": "<span class='label label-default m-l-sm'>${name}:${index}</span> " }, { "type": "each", "name": "subList", "items": [ { "type": "tpl", "tpl": "<span class='label label-default m-l-sm'>${itemOutter.name}-${item}:${indexOutter}-${index}</span> " } ] } ] }

示例数据为{"name": "a", "subList": ["a1", "a2"]}等三条。内层模板${itemOutter.name}-${item}:${indexOutter}-${index}按示例数据的第一条展开,文档示例输出形如a-a1:0-0a-a2:0-1。判断嵌套是否正确:内层输出里能同时看到外层的itemOutter.name、外层索引indexOutter和内层itemindex,四者一一对应。

这里也能解释上一节的冲突问题:外层改用了自定义键名后,即使成员对象自带index字段,也不会影响内层默认index对最内层索引的读取。

可选:在 Table 列、Form 静态展示中使用

each用在 Table 的列配置、List 内容、Card 卡片内容或表单的 Static-XXX 中时,可以设置name属性映射同名变量,然后用item获取单项值。文档给出了 Table 列的完整示例:

{ "type": "table", "data": { "items": [ {"id": "1", "each": ["A1", "B1", "C1"]}, {"id": "2", "each": ["A2", "B2", "C2"]}, {"id": "3", "each": []} ] }, "columns": [ {"name": "id", "label": "Id"}, { "name": "each", "label": "循环", "type": "each", "placeholder": "暂无内容", "items": { "type": "tpl", "tpl": "<span class='label label-info m-l-sm'>${item}</span>" } } ] }

示例中第三行each是空数组,此时展示placeholder指定的"暂无内容",这正是空数组场景的验证点。List 内容、Card 内容的配置方式相同(文档原文"List 的内容、Card 卡片的内容配置同上")。

表单静态展示场景,each作为表单项设置namelabel,用item输出单个值;文档另有一个"动态表单项"示例,通过source+index生成text${index}命名的多个input-text,该能力从 3.5.0 版本开始支持(见 each.md 对应章节)。

如何验证渲染结果

仓库中的单测 Each.test.tsx 展示了各场景的可断言结果,可作为核对渲染行为的标准:

  • 基础用法:arr为 3 个元素时,页面渲染出 3 个.cxd-Each .cxd-TplField节点,第一个节点文本为A
  • 对象数组(直接传value):2 个成员时第二个节点文本为martin:1,即字段值 + 索引;
  • source数据映射:2 个对象成员时渲染 2 个.cxd-Wrapper,第二个节点文本为age: 29
  • Form 静态展示:.cxd-Form .cxd-Each节点存在。

对照页面时按同样思路检查:节点数量是否等于数组长度、节点文本是否为字段:索引${item}的预期值、空数组是否落入placeholder分支。

限制与注意事项

  • namesource同时存在时,name优先。
  • 成员对象自带index字段会覆盖循环索引变量,文档明确指向"循环嵌套"章节的itemKeyName/indexKeyName方案解决。
  • value不存在或为空数组时走placeholder占位,不会渲染任何items节点。
  • 循环次数上限:Each.tsx 源码中支持maxLength属性,超过时截取前maxLength项,该属性未在文档属性表中列出,按源码行为对待。
  • 嵌套层数不限,但只有最内层能用默认的item/index,外层一律通过自定义键名访问。

更多场景(Table 列、Form 动态表单项的完整示例)以 Each 循环渲染器文档 为准。

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

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

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

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

立即咨询