amis Page 页面组件完全指南顶级容器、数据初始化与事件动作实战【免费下载链接】amis前端低代码框架通过 JSON 配置就能生成各种页面。项目地址: https://gitcode.com/GitHub_Trending/am/amisPage 组件是 amis 页面 JSON 配置中的顶级容器组件是整个页面配置的入口负责承载内容区body、侧边栏aside、工具栏toolbar等区域并统一管理页面级数据初始化、轮询刷新、下拉刷新、样式定制与事件动作。阅读完本文你将掌握 Page 组件的全部核心属性、区域划分方式、initApi 数据拉取与轮询停止条件、CSS 变量与自定义 CSS 用法以及 reload / setValue 等动作和 init / inited / pullRefresh 事件的完整配置方法。Page 组件定位整个页面的入口容器在 amis 中一个页面的顶层 JSON 通常就是type: page的节点它可以理解为整棵渲染树的根。Page 不只是一个普通容器它同时承担了页面的数据域职责Page 通过 initApi 获取的初始数据会合并到整个页面作用域中所有子组件都可以通过${变量名}直接引用。从源码看Page 的实现位于 packages/amis/src/renderers/Page.tsx其默认属性static defaultProps见 Page.tsx为asideSticky: true侧边栏默认吸顶固定asidePosition: left侧边栏默认在左侧pullRefresh: {disabled: true}下拉刷新默认关闭initFetch: true默认拉取 initApi 数据。同时 Page 内部基于IServiceStore见 packages/amis-core/src/store/service.ts管理加载态与请求store.loading会驱动内容区的 Spinner请求出错时会展示错误 Alert。基本用法与组件渲染渲染一段文字最简单的方式是在body中直接放一段文本Page 会把它当作模板渲染{ type: page, title: 标题, body: Hello World! }渲染任意组件body是一个 SchemaNode支持传入任意 amis 组件或组件数组。例如渲染一个提交到/api/mock2/form/saveForm的表单{ type: form, api: /api/mock2/form/saveForm, body: [ { type: input-text, name: name, label: 姓名 } ] }body中的组件渲染由render(body, body || , subProps)完成见 Page.tsx子组件会自动继承 Page 的数据作用域与onAction、onQuery、onChange、onBulkChange等回调这正是页面级数据得以在组件间流转的机制。页面区域划分body、aside 与 toolbarPage 默认将页面划分为三个区域均可配置任意组件或内容内容区body页面主体占据剩余宽度侧边栏aside页面左侧默认或右侧的边栏工具栏toolbar页面右上角存在 title 时或顶部无 title 时。{ type: page, aside: [ { type: tpl, tpl: 这是侧边栏部分 } ], toolbar: [ { type: tpl, tpl: 这是工具栏部分 } ], body: [ { type: tpl, tpl: 这是内容区 } ] }不同区域都是 Page 的子节点也就是说都可以使用 Page 下数据作用域。从渲染实现上看Page.tsx只有配置了aside且非空时外层容器才会加上Page--withSidebar样式类配合asideSticky会追加Page--asideSticky配合asidePosition会追加Page--${asidePosition}Aside。另外还可以通过regions属性显式声明需要渲染的区域Arrayaside | body | toolbar | header默认会按配置内容自动决定。页面初始化请求initApi通过配置initApi可以在初始化页面时请求指定接口返回数据整体合并进 Page 数据域供整个页面使用{ type: page, initApi: /api/mock2/page/initData, body: [ { type: tpl, tpl: 当前时间是${date} } ] }具体 API 规范查看 API 文档。底层机制initFetch / initFetchOn结合源码Page.tsxPage 挂载后依次执行派发init事件dispatchEvent(init, data, this)如果事件被prevented则中断初始化流程若配置了全局 tracker会上报pageLoaded事件通过isEffectiveApi(initApi, store.data, initFetch, initFetchOn)判断是否需要拉取随后调用store.fetchInitData(...)并串联initInterval轮询。其中initFetch默认true是否起始拉取 initApi设为false可关闭初始请求initFetchOn用表达式条件控制是否起始拉取。在componentDidUpdatePage.tsx中还有增量逻辑当initFetchOn从假变为真、或initApi因 URL 变量变化而过期时会自动重新拉取数据实现条件触发 参数变化自动刷新。对应的测试覆盖位于 packages/amis/tests/renderers/Page.test.tsx包括Renderer:Page initApi、initApi initFetch:false、initApi initFetchOn - true/false、initApi error show Message、initApi show loading等用例可用于验证上述行为。轮询初始化接口interval 与 stopAutoRefreshWhen想要在页面渲染后轮询请求初始化接口只需两步配置initApi配置interval单位为毫秒最小 1000。{ type: page, initApi: /api/mock2/page/initData, interval: 3000, body: [ { type: tpl, tpl: 当前时间是${date} } ] }如果希望在满足某个条件时停止轮询配置stopAutoRefreshWhen表达式{ type: page, initApi: /api/mock2/page/initData, stopAutoRefreshWhen: this.time % 5, // 当时间戳能被5整除时停止轮询 interval: 3000, body: [ { type: tpl, tpl: 当前时间戳是${date} } ] }源码视角的轮询逻辑核心逻辑在initIntervalPage.tsx每次请求完成后先派发inited事件并携带responseData、responseStatus、responseMsg及当前数据域字段仅当value?.ok接口正常返回、配置了interval、组件仍挂载且!stopAutoRefreshWhen || !evalExpression(stopAutoRefreshWhen, data)时才用setTimeout调度下一次刷新间隔强制Math.max(interval, 1000)保证不小于 1000ms若配置silentPolling: true则静默轮询不显示加载动画对应调用silentReload。注意interval属性表中默认值为3000即不配置时默认每 3 秒轮询一次前提是配置了 initApi。下拉刷新pullRefresh移动端通过配置pullRefresh可以启用移动端下拉刷新能力disabled默认true需要显式关闭{ type: page, initApi: /api/mock2/page/initData, pullRefresh: { disabled: false }, body: [ { type: tpl, tpl: 当前时间是${date} } ] }还可以自定义下拉过程中的提示文案{ type: page, initApi: /api/mock2/page/initData, pullRefresh: { disabled: false, pullingText: 继续下拉, loosingText: 可以释放了 }, body: [ { type: tpl, tpl: 当前时间是${date} } ] }从源码看Page.tsx只有处于mobileUI模式且pullRefresh.disabled ! true时内容区才会被PullRefresh组件包裹下拉释放后触发handleRefresh先派发pullRefresh事件可被prevented拦截再调用this.reload()重新拉取 initApi 数据。样式定制CSS 变量与自定义 CSScssVars页面级 CSS 变量通过设置 CSS 变量几乎可以修改 amis 中任意组件的展现具体细节请参考样式。示例将全局文本色改为蓝色主题色{ type: page, cssVars: { --text-color: #108cee }, body: { type: form, body: [ { type: input-text, label: 文本框, name: text } ] } }源码中updateVarStylePage.tsx会把cssVars逐项拼进:root { ... }并注入一个style标签且componentDidUpdate中会对cssVars做 JSON 对比变化时自动重建样式实现主题热更新。css直接编写自定义样式1.3.0虽然 amis 提供了很多内置样式但想要更精细控制样式最好的方式依然是编写自定义 CSS。在之前的版本中需要外部页面配合从1.3.0开始 amis 可以直接在配置中支持自定义 CSS{ type: page, css: { .myClass: { color: blue } }, body: { type: tpl, tpl: 文本, className: myClass } }上面的配置会自动创建一个style标签其中内容就是.myClass { color: blue; }配置写法和编写普通 CSS 的体验一致可以使用任意 CSS 选择符及属性。对应实现是updateStyle并同样在css/mobileCSS变化时自动重建Page.tsx组件卸载时会移除注入的style节点避免样式残留Page.tsx。侧边栏进阶宽度调整、吸顶与位置aside 可调整宽度通过配置asideResizor可以让侧边栏支持拖动调整宽度同时用asideMinWidth、asideMaxWidth限定范围{ type: page, asideResizor: true, asideMinWidth: 150, asideMaxWidth: 400, aside: [ { type: tpl, tpl: 这是侧边栏部分 } ], body: [ { type: tpl, tpl: 这是内容区 } ] }开启asideResizor后aside 容器会添加relative类并渲染一个拖拽手柄Page-asideResizor通过onMouseDown{this.handleResizeMouseDown}实现宽度拖拽Page.tsx。aside 位置固定通过配置asideSticky开关侧边栏吸顶默认开启true。关闭后侧边栏会跟随页面滚动。aside 展示位置通过配置asidePosition控制侧边栏展示位置取值为left | right默认left{ type: page, asideResizor: true, asidePosition: right, aside: [ { type: tpl, tpl: 这是侧边栏部分 } ], body: [ { type: tpl, tpl: 这是内容区 } ] }属性表属性名类型默认值说明typestringpage指定为 Page 组件titleSchemaNode页面标题subTitleSchemaNode页面副标题remarkRemark标题附近会出现一个提示图标鼠标放上去会提示该内容。asideSchemaNode往页面的边栏区域加内容asideResizorboolean页面的边栏区域宽度是否可调整asideMinWidthnumber页面边栏区域的最小宽度asideMaxWidthnumber页面边栏区域的最大宽度asideStickybooleantrue用来控制边栏固定与否asidePositionleft \| rightleft页面边栏区域的位置toolbarSchemaNode往页面的右上角加内容需要注意的是当有 title 时该区域在右上角没有时该区域在顶部bodySchemaNode往页面的内容区域加内容classNamestring外层 dom 类名cssVarsobject自定义 CSS 变量请参考样式toolbarClassNamestringv-middle wrapper text-right bg-light b-bToolbar dom 类名bodyClassNamestringwrapperBody dom 类名asideClassNamestringw page-aside-region bg-autoAside dom 类名headerClassNamestringbg-light b-b wrapperHeader 区域 dom 类名initApiAPIPage 用来获取初始数据的 api。返回的数据可以整个 page 级别使用。initFetchbooleantrue是否起始拉取 initApiinitFetchOn表达式是否起始拉取 initApi, 通过表达式配置intervalnumber3000刷新时间(最小 1000)silentPollingbooleanfalse配置刷新时是否显示加载动画stopAutoRefreshWhen表达式通过表达式来配置停止刷新的条件pullRefreshobject{disabled: true}下拉刷新配置仅用于移动端事件表当前组件会对外派发以下事件可以通过onEvent来监听这些事件并通过actions来配置执行的动作在actions中可以通过${事件参数名}或${event.data.[事件参数名]}来获取事件产生的数据详细请查看事件动作。[name]为当前数据域中的字段名例如当前数据域为{username: amis}则可以通过${username}获取对应的值。事件名称事件参数说明init-组件实例被创建并插入 DOM 中时触发。2.4.1 及以上版本initedresponseData: any请求的响应数据responseStatus: number响应状态0 表示成功responseMsg: string响应消息,error表示接口是否成功[name]: any当前数据域中指定字段的值initApi 接口请求完成时触发pullRefresh-开启下拉刷新后下拉释放后触发仅用于移动端init 和 inited 示例下面的配置分别在组件挂载时init弹出提示并在 initApi 请求完成后inited以 JSON 形式弹出响应数据{ type: page, initApi: /api/mock2/page/initData, body: [ { type: tpl, tpl: 当前时间是${date} } ], onEvent: { init: { actions: [ { actionType: toast, args: { msgType: info, msg: init } } ] }, inited: { actions: [ { actionType: toast, args: { msgType: info, msg: ${event.data.responseData|json} } } ] } } }需要说明的是inited事件的参数来自initInterval中的dispatchEvent(inited, ...)Page.tsx其构造的数据对象包含responseData、responseStatus接口失败时取 store 错误态为 1成功为 0与responseMsg与事件表描述完全一致。动作表当前组件对外暴露以下特性动作其他组件可以通过指定actionType: 动作名称、componentId: 该组件id来触发这些动作动作配置可以通过args: {动作配置项名称: xxx}来配置具体的参数详细请查看事件动作。动作名称动作配置说明reload-重新加载调用initApi刷新数据域数据setValuevalue: object更新的数据更新数据reload只做刷新重新发送initApi请求刷新 Page 时只配置componentId目标组件 ID 即可{ type: page, id: page_reload_1, initApi: /api/mock2/page/initData, body: [ { type: button, label: 刷新Page数据加载请求, className: mb-2, onEvent: { click: { actions: [ { componentId: page_reload_1, actionType: reload } ] } } }, { type: tpl, tpl: 当前时间是${date} } ] }发送数据并刷新刷新 Page 组件时如果配置了data将先发送data给目标组件并将该数据合并到目标组件的数据域中如果配置dataMergeMode: override将覆盖目标组件的数据然后重新请求数据{ type: page, id: page_reload_2, initApi: /api/mock2/page/initData, body: [ { type: button, label: 刷新Page数据加载请求并将我的年龄设置为18, className: mb-2, onEvent: { click: { actions: [ { componentId: page_reload_2, actionType: reload, data: { age: 18 } } ] } } }, { type: tpl, tpl: 当前时间是${date} 我的年龄${age|default:-} } ] }源码层面reload动作最终落到reload(query, ...)Page.tsx若带 query 则先receive合并数据并触发重拉否则clearTimeout取消旧轮询、调用store.fetchData(initApi, store.data, {silent})重新请求并重新进入initInterval。setValue通过setValue更新指定页面组件的数据。合并数据默认setValue会将新数据与目标组件数据进行合并store.updateData合并语义{ type: page, id: page02, initApi: /api/mock2/page/initData, body: [ { type: button, label: 更新数据, className: mb-2, onEvent: { click: { actions: [ { componentId: page02, actionType: setValue, args: { value: {date: 2023-05-01} } } ] } } }, { type: tpl, tpl: 标题${title} 当前时间是${date} } ] }覆盖数据可以通过dataMergeMode: override来覆盖目标组件数据{ type: page, id: page02, initApi: /api/mock2/page/initData, body: [ { type: button, label: 更新数据, className: mb-2, onEvent: { click: { actions: [ { componentId: page02, actionType: setValue, args: { value: {date: 2023-05-01} }, dataMergeMode: override } ] } } }, { type: tpl, tpl: 标题${title|default:-} 当前时间是${date} } ] }对比两种模式可以直观看到合并模式下title保持原有值示例中initApi返回的数据里若含 title 则保留覆盖模式下title因数据被整体替换而回退到默认值-。小结Page 组件是 amis 页面配置的骨架与数据中枢理解它的三个关键能力即可驾驭大多数页面场景区域编排通过body/aside/toolbar组织页面布局配合asideResizor、asideSticky、asidePosition精细控制侧边栏数据加载initApiinitFetch/initFetchOn控制初始拉取intervalstopAutoRefreshWhensilentPolling实现智能轮询pullRefresh覆盖移动端下拉刷新交互联动通过onEvent监听init/inited/pullRefresh事件通过reload/setValue动作让其他组件反向控制 Page 的数据与刷新配合cssVars/css完成主题与精细样式定制。若要进一步验证或深入阅读可对照源码 packages/amis/src/renderers/Page.tsx 与测试 packages/amis/tests/renderers/Page.test.tsx 进行学习。【免费下载链接】amis前端低代码框架通过 JSON 配置就能生成各种页面。项目地址: https://gitcode.com/GitHub_Trending/am/amis创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考