amis Each 循环渲染器怎么遍历数组并处理对象数组与嵌套循环
【免费下载链接】amis前端低代码框架,通过 JSON 配置就能生成各种页面。项目地址: https://gitcode.com/GitHub_Trending/am/amis
在 amis 中,页面内容由 JSON schema 描述。当数据是数组、需要"每个元素生成一个子渲染器"时,用each组件完成:遍历简单数组、遍历对象数组并输出字段、两层嵌套循环,都能用同一套name+items的配置写出来。本文按这三个任务展开,每一步都给出可直接使用的 schema 和判断渲染是否正确的依据。
核心配置来自 Each 循环渲染器文档,先记住属性表中与遍历直接相关的几项:
| 属性名 | 类型 | 说明 |
|---|---|---|
name | string | 获取数据域中变量,指定要循环的数组 |
source | string | 获取数据域中变量,支持数据映射 |
items | object | 使用value中的数据,循环输出渲染器 |
placeholder | string | 当value值不存在或为空数组时的占位文本 |
itemKeyName | string | 获取循环当前数组成员,默认item |
indexKeyName | string | 获取循环当前索引,默认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 的"基本用法"),渲染结果是三个标签A、B、C。判断是否生效:页面中出现 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:0、b:1、c:2这样的标签(示例结果,按示例数据推断)。
文档中有一条明确提醒:如果成员对象本身也有名为index的字段,会覆盖循环索引变量,导致取不到真正的索引。此时改用下一节的itemKeyName/indexKeyName自定义字段名来规避。
嵌套循环:用 itemKeyName 和 indexKeyName 取上层数据
官方文档说明:存在嵌套使用时,默认的item或者index始终拿的是最里面那层的信息;要获取上层each的信息,需要自定义itemKeyName和indexKeyName指定字段名。
以文档"循环嵌套"示例为例,外层数组每个成员带有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-0、a-a2:0-1。判断嵌套是否正确:内层输出里能同时看到外层的itemOutter.name、外层索引indexOutter和内层item、index,四者一一对应。
这里也能解释上一节的冲突问题:外层改用了自定义键名后,即使成员对象自带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作为表单项设置name、label,用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分支。
限制与注意事项
name与source同时存在时,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),仅供参考