Skip to content
On this page

响应式变量与实时文字

响应式变量是 ChaUI 最值得优先掌握的能力之一。页面不需要反复执行“找到文本,再把内容改成新字符串”的脚本;只要让文字、布局或条件引用变量,变量变化后,界面就会自动使用最新结果重新显示。

它适合制作生命值、余额、倒计时、任务进度、选择状态、分页数字和实时提示等动态界面。

一个最直观的例子

先在页面默认变量中准备计数:

yaml
vars:
  count: 0 # 页面刚打开时从 0 开始

然后让文本内容引用它:

yaml
text:
  value: "已经点击 {vars.count} 次"

按钮脚本只负责修改变量:

text
vars.count = vars.count + 1

每次点击后,页面都会立即显示新的次数。文本组件不需要额外的修改文字脚本。

页面生命周期同样可以驱动响应式刷新。events.open、组件 events.create 或自定义方法修改变量后,文字、布局、显隐条件和按钮选中状态会在接下来的渲染中使用最新值;不需要手动刷新页面。

yaml
events:
  open: 方法.初始化()
methods:
  初始化: |-
    vars.title = "欢迎回来"
    vars.ready = true

花括号中的内容才会计算

text.valuebutton.label 只有 {...} 内的内容会作为表达式读取,花括号外的文字保持原样。

text
玩家生命:{vals.player.health} / {vals.player.maxHealth}
任务进度:{vars.current} / {vars.total}
完成比例:{vars.current / vars.total * 100}%

可以在同一段文字中放入多个表达式,也可以使用四则运算、括号和数学函数

text
剩余生命:{vals.player.maxHealth - vals.player.health}
面板数值:{(vars.base + vars.extra) * 2}

数字结果会自动去掉没有意义的末尾小数,例如 10.0 会显示为 10

输出普通花括号

如果内容本身需要显示花括号,使用双花括号:

写成“两个连续的左花括号 + vars.count + 两个连续的右花括号”时,页面会显示普通的 {vars.count},不会读取变量。

两个连续的左花括号输出一个左花括号,两个连续的右花括号输出一个右花括号。

三类常用值

页面变量 vars

页面变量属于当前打开的页面会话,可以由默认配置、组件脚本或服务端业务更新。

yaml
vars:
  playerName: "旅行者"
  count: 0
  ready: false
text
欢迎回来,{vars.playerName}
点击次数:{vars.count}
是否准备:{vars.ready}

中文前缀也可以写成 变量,例如 {变量.count}

玩家常量 vals.player

玩家常量来自当前客户端玩家状态,只能读取,不能由脚本赋值。最常见的写法如下:

text
生命:{vals.player.health} / {vals.player.maxHealth}
护甲:{vals.player.armor} 等级:{vals.player.experienceLevel}
主手:{vals.player.inventory.mainhand.id} × {vals.player.inventory.mainhand.count}

玩家基础状态、36 格背包汇总、主手、副手和全部盔甲字段及中文别名,请查阅只读常量。需要直接显示和操作真实背包槽位时,再查阅背包映射表

鼠标常量 vals.mouse

鼠标常量使用 Minecraft GUI 缩放坐标,并会随鼠标移动和按键状态实时更新。例如:

text
鼠标:{vals.mouse.x}, {vals.mouse.y} 左键:{vals.mouse.leftDown}

左右中键状态和全部中文写法见只读常量

PAPI 常量 vals.papi

PAPI 常量由服务端 PlaceholderAPI 解析,再以只读常量提供给页面。客户端不需要安装占位符扩展,也不会自行解析 %placeholder%

下面是一份完整页面示例:

yaml
id: player_status
version: 1
title: 玩家状态
size:
  width: window.width
  height: window.height
coordinateMode: absolute
display:
  mode: screen
  screen:
    dimBackground: true
vars:
  title: "角色信息" # 普通页面默认变量
papi:
  refreshTicks: 20 # 每 20 tick 刷新一次;允许 5 至 1200,默认 20
  values:
    balance: "%vault_eco_balance%" # 页面中使用 vals.papi.balance
    prefix: "%luckperms_prefix%" # 页面中使用 vals.papi.prefix
elements:
  - id: status_text
    type: text
    parent: ""
    visible: true
    enabled: false
    pointerEvents: pass
    scale: 1
    opacity: 1
    z: 10
    layout:
      x: window.width * 0.5 - 100
      y: 30
      width: 200
      height: 36
    text:
      value: "{vars.title}\n称号:{vals.papi.prefix}\n余额:{vals.papi.balance}"
      font: ""
      color: "#FFFFFF"
      textSize: 1
      textLineLength: 0
      revealIntervalMs: 0
      align: center
    tooltip: []
    events: {}

values 左侧是页面内使用的安全名称,右侧是 PlaceholderAPI 模板。名称 balance 会映射为 {vals.papi.balance}

PAPI 常量名称可以使用字母、数字、下划线和 Unicode 字符,但不能以数字开头。一个页面最多配置 64 项。

刷新与共享

  • 页面打开后会立即取得一次 PAPI 常量,不必等待第一个刷新周期。
  • refreshTicks 控制刷新频率,默认 20,约为一秒一次。
  • 值没有变化时,页面会继续显示当前结果,不会产生可见闪烁。
  • 同一玩家同时打开同一个页面的多个实例时,会共享该页面的 PAPI 刷新结果。
  • 页面不再使用后,相关刷新会停止;重新打开时重新取得最新值。
  • 服务端没有安装 PlaceholderAPI 时,ChaUI 其他页面仍可正常使用;未取得的表达式会保留原占位内容,方便发现配置问题。

不要为了追求“更实时”盲目把刷新间隔设为 5。余额、称号等变化较慢的内容通常使用 20100 就足够;只有确实需要快速变化的内容才应缩短间隔。

不只文字会响应

同一份变量还可以同时驱动布局、显示条件和按钮文字:

yaml
vars:
  progress: 0.35
  ready: false

elements:
  - id: progress_text
    type: text
    visibleWhen: "vars.progress > 0"
    layout:
      x: 20
      y: 20
      width: 160
      height: 16
    text:
      value: "进度:{vars.progress * 100}%"

  - id: confirm_button
    type: button
    enabledWhen: "vars.ready == true"
    layout:
      x: 20
      y: 45
      width: 100
      height: 20
    button:
      label: "当前进度 {vars.progress * 100}%"

服务端或脚本修改 progress 后,文字、按钮标签和引用该变量的布局会在同一页面状态下更新。这就是响应式页面的核心价值:只维护数据,界面自动跟随数据变化。

页面 yml 中直接填写的布局公式本身就是响应式的。若公式由点击事件或方法在运行时写入,需要显式使用 formula(...)

yaml
events:
  leftClick: |-
    component("progress_text").layout.x = formula(
      component("progress_bar").layout.x + component("progress_bar").layout.width + 4
    )

如果去掉 formula,右侧只会在点击时计算一次并保存为固定数字。

无效表达式如何处理

未知变量、缺失 PAPI 常量或不完整表达式不会让页面崩溃,而是保留原占位内容:

text
余额:{vals.papi.unknown}
错误公式:{vars.count + }

如果游戏中仍看到花括号内容,请依次检查变量名、PAPI 映射名、表达式拼写和服务端 PlaceholderAPI 扩展是否可用。

推荐实践

  1. 页面状态统一放进 vars,文字只负责展示。
  2. 玩家本地状态使用 vals.player,服务端插件变量使用 vals.papi
  3. 需要自动显隐时使用 visibleWhen,不要每帧执行脚本。
  4. PAPI 映射使用清楚的短名称,例如 balancerankquestProgress
  5. 对外展示的数字可以在表达式中运算,但复杂业务结果更适合先由服务端变量计算完成。

继续阅读语法与事件,可以学习如何用分号在单行输入框中组合多条脚本。