页面生命周期与自定义方法
ChaUI 页面可以在打开、组件创建和关闭时自动执行脚本。配合自定义方法,你可以把初始化、刷新和收尾逻辑集中写在页面根部,再从不同事件中调用,避免同一段脚本散落在多个组件里。
三类生命周期事件
| 配置位置 | 事件 | 触发时机 |
|---|---|---|
页面根级 events.open | 页面打开 | 新页面作用域建立后最先执行 |
组件 events.create | 组件创建 | open 之后按页面组件顺序执行;脚本新增或复制的组件也会执行一次 |
页面根级 events.close | 页面关闭 | 普通关闭、HUD/世界实例关闭和 reload 更换旧页面时执行 |
一次正常打开的固定顺序是:页面 open → 每个初始组件的 create。同一个组件对象只执行一次 create;删除后重新创建的同 ID 组件属于新对象,会再次触发。
执行 open 前,当前页面会话的组件对象树和父子引用已经建立,因此初始化方法可以直接读取组件、父布局和原始公式,也可以安全建立跨组件布局公式。
vars:
opened: false
title: "准备中"
events:
open: |-
方法.初始化()
close: |-
vars.opened = false
methods:
初始化: |-
vars.opened = true
vars.title = "页面已经就绪"
elements:
- id: title
type: text
layout:
x: 20
y: 20
width: 180
height: 20
text:
value: "{vars.title}"
events:
create: vars.title = "标题组件已创建"自定义方法
页面根级 methods 使用“方法名: 脚本”保存可复用逻辑。方法不接收参数,也不返回结果,但会直接共享当前页面的 vars、组件临时状态和只读常量。
methods:
refresh: |-
vars.count = vars.count + 1
component("status").visible = true
component("status").layout.x = formula(component("panel").layout.x + 8)英文调用:
methods.refresh()中文调用:
方法.refresh()方法可以继续调用其他方法。ChaUI 会拒绝未知方法、直接递归和间接递归;调用展开最多 16 层,一次同步事件最多执行 4096 个脚本节点。方法也不能用来绕过 repeat、timer 中禁止批量执行高权限动作的限制。
动态组件的 create
addComponent 和 copyComponent 创建的是当前页面会话里的临时组件。创建成功后,新组件的 events.create 会立即执行一次:
copyComponent("card_template", "card_2")临时组件不会自动写回页面文件。重新打开页面后,它们会恢复为保存时的结构。
保存校验会扫描当前页面全部生命周期事件、组件事件、自定义方法和计时器回调中的静态 addComponent / copyComponent 声明。因此可以在 open 中创建组件,再在按钮事件或方法中引用同一个动态 ID:
events:
open: |-
addComponent("text", "dynamic_tip")
methods:
更新提示: |-
component("dynamic_tip").text.value = "数据已经刷新"这只解决编辑器保存时的类型识别,不改变运行顺序。如果方法在组件实际创建前执行,对动态组件的那条操作会安全跳过。
reload 的关闭与重开
执行 /chaui reload 时,普通页面、HUD 和每一个世界页面实例都会经历完整生命周期:
- 旧页面执行
close; - 旧页面的计时器、视频、字体和实体资源被释放;
- 服务端载入新页面定义;
- 客户端短暂等待 1 tick;
- 新页面重新执行
open和全部初始create。
如果页面已经从配置中删除,只执行旧页面关闭,不再重新打开。关闭确认最多等待 40 tick;未送达的动作不会被服务端自行补造。
GUI 带有子页面时,旧页面先从栈顶一路关闭到根页面;重载完成后再先恢复根页面,然后逐层恢复到原栈顶。每一层都拥有独立变量、输入、计时器和资源作用域,也会分别执行自己的 close、open 与 create。如果某一层页面已经缺失、配置无效或不再是 screen,恢复会停在这一层,已经成功恢复的父级仍然保留。容器替换页面作为根页面时,只重建 ChaUI 页面链,不会为了 reload 关闭真实容器。
关闭中间父页面也遵循栈顺序:先从栈顶向下关闭它上方的所有子页面,再关闭目标页面。closeAll() 会一次处理当前 GUI 从栈顶到根页面的整条链,但不会影响 HUD 或世界页面。
客户端与服务端的分工
变量、组件状态、音效、视频控制和生命周期流程在客户端执行。open、close、cmd、opcmd、consolecmd 等需要服务端参与的动作,只会上报本次实际执行到的动作编号;服务端会从已保存页面和方法中重新确认后执行,不接收客户端上传的命令正文。
编辑器预览
编辑画布本身不执行任何生命周期。点击“预览”后,编辑器会建立页面深拷贝并在本地执行 open、create、点击、悬浮和 close。预览中的变量、组件修改和临时组件不会污染待保存页面,也不会发送服务端动作或自定义 packet。
退出预览会立即停止预览计时器并释放视频、字体和实体资源。
猹件开发组