快速上手
用四个可预览示例掌握 body、State、控件和导航。
这篇教程用四个可预览示例串起 AppUI 的最小闭环:显示页面、修改状态、编辑表单、列表进详情。每段都可以直接运行。
#1. Hello World
先让原生页面出现。body() 返回一个 View,脚本末尾调用 appui.run(body)。
已复制
import appui
def body():
return appui.NavigationStack(
appui.VStack([
appui.Text("Hello AppUI").font("title2").bold(),
appui.Text("用 Python 编写原生 MiniApp 界面")
.foreground_color("secondaryLabel"),
], spacing=8)
.padding()
.navigation_title("Hello")
)
appui.run(body)
预期效果:预览显示一个带导航标题的原生页面,页面中有标题和说明文字。
#2. State 和按钮
用 State 保存页面数据。按钮回调修改状态后,页面会用新状态重建。
已复制
import appui
state = appui.State(count=0, message="Ready")
def decrease():
state.batch_update(count=state.count - 1, message="Decreased")
def increase():
state.batch_update(count=state.count + 1, message="Increased")
def body(view_state):
return appui.NavigationStack(
appui.VStack([
appui.Text(f"当前计数:{view_state.count}").font("title3"),
appui.HStack([
appui.Button("-1", action=decrease).button_style("bordered"),
appui.Button("+1", action=increase)
.button_style("bordered_prominent"),
], spacing=12),
appui.Text(view_state.message)
.font("caption")
.foreground_color("secondaryLabel"),
], spacing=16)
.padding()
.navigation_title("状态")
)
appui.run(body, state=state)
预期效果:点击 +1 或 -1 后计数和状态文案同步变化。
#3. 表单控件
设置页和编辑页优先使用 Form + Section。输入控件通过 on_change 写回 State。
已复制
import appui
state = appui.State(name="Ada", enabled=False, volume=40.0, saved=False)
def set_name(value):
state.batch_update(name=value, saved=False)
def set_enabled(value):
state.batch_update(enabled=value, saved=False)
def set_volume(value):
state.batch_update(volume=value, saved=False)
def save():
state.saved = bool(state.name.strip())
def body():
footer = "已保存" if state.saved else "修改后点击保存"
return appui.NavigationStack(
appui.Form([
appui.Section("资料", [
appui.TextField("姓名", text=state.name, on_change=set_name),
appui.Toggle("启用提醒", is_on=state.enabled, on_change=set_enabled),
appui.Slider(
value=state.volume,
minimum=0,
maximum=100,
on_change=set_volume,
),
], footer=footer),
appui.Section("操作", [
appui.Button("保存", action=save)
.button_style("bordered_prominent"),
]),
]).navigation_title("表单")
)
appui.run(body, state=state)
预期效果:修改文本、开关或滑块后页面保持响应;点击保存后底部文案变为“已保存”。
#4. 导航和列表
多页面 MiniApp 通常用 NavigationStack 包根页面,列表进详情用 NavigationLink。动态行必须有稳定 key。
已复制
import appui
items = [
{"id": "docs", "title": "文档", "subtitle": "Guide"},
{"id": "api", "title": "API", "subtitle": "Reference"},
{"id": "demo", "title": "示例", "subtitle": "Cookbook"},
]
state = appui.State(last_opened="None")
def item_key(item):
return item["id"]
def mark_opened(item):
state.last_opened = item["title"]
def detail_view(item):
def open_current():
mark_opened(item)
return appui.Form([
appui.Section("详情", [
appui.LabeledContent("标题", value=item["title"]),
appui.LabeledContent("类型", value=item["subtitle"]),
appui.Button("标记打开", action=open_current),
]),
appui.Section("状态", [
appui.LabeledContent("Last opened", value=state.last_opened),
]),
]).navigation_title(item["title"])
def row_view(item):
label = appui.HStack([
appui.Text(item["title"])
.frame(max_width=appui.infinity, alignment="leading"),
appui.Text(item["subtitle"]).foreground_color("secondaryLabel"),
])
return appui.NavigationLink(destination=detail_view(item), label=label)
def body():
return appui.NavigationStack(
appui.List([
appui.Section("入口", [
appui.ForEach(items, row_builder=row_view, key=item_key),
])
]).navigation_title("列表")
)
appui.run(body, state=state)
预期效果:列表显示三行入口,点击任一行进入详情页;详情页按钮会更新打开状态。
#发布前检查
| 检查项 | 合格标准 |
|---|---|
| 入口 | 脚本末尾只调用一次 appui.run(...) |
| 呈现 | 默认 presentation='sheet';全屏可用 'fullscreen' 或 'fullscreen_with_close' |
| 页面 | body() 或 body(state) 返回 AppUI View |
| 状态 | 回调修改 State,多字段更新用 batch_update(...) |
| 按钮 | action 传命名函数,不写 action=save() |
| 输入 | on_change 接收新值并写回 State |
| 列表 | ForEach 使用稳定 key |
#失败路径
- 预览空白:确认
body()返回 View,且脚本末尾调用了appui.run(...)。 - 按钮没反应:确认
action传函数本身,而不是函数调用结果。 - 输入不更新:确认
on_change的参数名接收新值,并写回State。 - 列表详情错乱:确认
ForEach使用稳定业务 id,不使用会变化的 index。 - 页面越来越难维护:回到 AppUI UI 模式,先选页面结构。
#API 参考
继续查 AppUI API 地图。需要判断该用哪个运行时时,先看 运行时选择。