> ## Documentation Index
> Fetch the complete documentation index at: https://guide.moyostory.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 页面代码与作品实时预览

> 让页面读取变量、提供规则选择器，并适配编辑器与玩家侧窗口。

页面代码决定模板的排版、样式和可点击元素。模板中间区域可以在“预览”和“代码”之间切换。

<img src="https://mintcdn.com/moyostory/2W8JKWEaiXD_6ckV/assets/editor/screenshots/page-code.jpg?fit=max&auto=format&n=2W8JKWEaiXD_6ckV&q=85&s=639000eaa5b9cdeb4360e00746a164d7" alt="“剧情页”的 TSX 模板代码编辑区" width="2327" height="1090" data-path="assets/editor/screenshots/page-code.jpg" />

<Note>
  101 提供可整段复制的页面代码。只有自定义布局或交互时，才需要直接修改代码。
</Note>

## 页面代码负责什么

* 读取 State 变量、Frame 变量和播放状态；
* 显示文字、背景、立绘、音频控件和选项；
* 为触发器规则提供稳定的 CSS 选择器；
* 适配作品实时预览和玩家侧运行窗口。

指令和触发器规则负责准备数据，页面代码负责读取并显示数据。

## 读取变量

页面代码可以使用变量占位符。常见形式：

```tsx theme={null}
const background = "{{frame.background}}"
const playerName = "{{state.player_name}}"
```

`frame.background` 来自当前帧，`state.player_name` 会在页面节点之间保留。变量不存在时，页面代码需要准备空值状态，避免整页报错。

媒体变量完成素材绑定后，占位符会得到可显示或播放的素材地址。绑定方法见[State 变量、Frame 变量与媒体绑定](/editor/variables-and-media)。

## 为触发器规则提供选择器

玩家点击后是否能触发规则，取决于页面元素是否匹配 Element Selector。

适合用于规则的标记：

* 固定功能使用类名，例如 `.story-next`；
* 多个选项使用共同类名和不同属性，例如 `.story-choice[data-route="letter"]`；
* 不要使用会随渲染顺序变化的临时编号。

修改类名或属性后，需要同步更新触发器规则。

## 页面尺寸规则

作品实时预览和运行预览都会把模板放入一个固定渲染窗口。页面根容器应填满该窗口：

```css theme={null}
html, body, #root, .template-root {
  width: 100%;
  height: 100%;
  min-width: 0;
  min-height: 0;
  margin: 0;
}
```

继续遵守以下约束：

* 根容器明确设置 `overflow`；
* 图片和立绘设置尺寸上限与 `object-fit`；
* 长内容放在内部滚动区域；
* 同时按可用宽度和高度限制固定比例舞台；
* 使用媒体查询、弹性布局或网格适配窄窗口。

根容器使用 `100vh` 并叠加内外边距时，可能产生超出渲染窗口的高度。使用 `height: 100%` 和 `box-sizing: border-box` 更容易保持稳定。

## 编译预览

从“代码”切回“预览”时，编辑器会编译当前草稿并刷新作品实时预览。

编译失败后：

* 编辑器会回到代码页；
* 代码编辑器底部显示可滚动的错误详情；
* 当前代码仍保留，可以继续修改；
* 新的编辑会清除旧错误提示。

作品实时预览只检查当前模板。跨页面跳转和真实 AI 生成需要保存后使用运行预览。

## 保存页面代码

点击顶部“保存作品”或关闭模板标签时选择“保存并关闭”，编辑器会：

1. 编译页面代码；
2. 保存模板和规则组；
3. 生成并上传模板预览图。

任一步出现错误时，查看提示并保留当前标签。保存完成前不要刷新页面。

<Tip>
  MoMo：页面按钮改了类名，触发器规则不会自动同步。改完代码后验证一次 CSS 选择器。
</Tip>
