工笔层染给生成式UI的启发:内容未齐,交互先别着急 一张动态卡片可能先有标题再有两项字段最后才收到允许提交的业务状态。把每次更新都当成“卡片完成”用户就会遇到按钮忽然可点、字段随后又变、焦点被挤走的问题。工笔画的层染可以用来理解这种展开底稿先稳定信息随后进入最终的交互权限另有一道工序。这是一种设计比喻不是渲染性能结论。它对应的工程问题是展示进度与允许操作的状态能否分别表达四个状态解决四种不同的等待empty尚未开始loading已请求但没有有效内容partial有内容但业务对象不完整ready才表示必要字段与约束已确认。失败与取消另外建模不能挤进“加载中”。外框稳定不等于把高度永远写死。短文本可以给合理最小高度长内容仍应允许扩展。图里四张卡片保持相同外框是为了对比状态不是在建议所有产品强制等高。10月更新的WebMCP说明将工具作为网页的渐进增强并保留用户可见的页面流程。对生成式界面我更关心这个含义Agent能调用功能并不意味着屏幕可以丢掉人与系统之间的状态解释。先验证状态机再接组件下面的模型不依赖Vue或React。字段是否齐全由业务确认字符流结束只表示传输结束两者缺一都不能提交。示例不把模型说出的“完成”当授权。import assert from node:assert/strict; function reduce(state, event) { if (event.type start) return { phase: loading, text: , complete: false }; if (event.type cancel) return { ...state, phase: cancelled }; if ([cancelled, failed, ready].includes(state.phase)) return state; if (event.type error) return { ...state, phase: failed }; if (event.type delta) return { ...state, phase: partial, text: state.text event.text }; if (event.type end) return { ...state, complete: true, phase: partial }; if (event.type validated state.complete) return { ...state, phase: ready }; return state; } let s reduce({}, { type: start }); s reduce(s, { type: delta, text: 两件商品 }); s reduce(s, { type: validated }); assert.equal(s.phase, partial); s reduce(s, { type: end }); s reduce(s, { type: validated }); assert.equal(s.phase, ready); s reduce(s, { type: cancel }); assert.equal(reduce(s, { type: delta, text: 迟到内容 }).text, s.text); console.log(progressive UI state checks passed);组件可以从phase派生按钮状态和辅助文案而不是在多处各维护一个isLoading。取消后的迟到事件不会继续追加开始新任务时则创建新状态不能悄悄复用旧结果。留白也包括给读者保留控制权加载时保持按钮位置部分内容到达后让用户能够阅读和停止完成前不要把未核验的金额或资格变成可提交事实。自动滚动只在用户仍处于末尾时跟随用户向上阅读后应停下。屏幕阅读器的播报也应按段落节制更新避免逐字抢占。Chrome的流式渲染建议讨论了重新解析历史内容的成本及富文本清洗。这里的状态机与这些问题互补解析器负责内容状态机负责什么时候允许用户依赖它。上面的JavaScript状态测试在Node v26.3.0通过CSS布局、焦点、无障碍播报和真实Agent调用未做浏览器集成测试。示例也不承诺完整JSON Schema校验需要业务另行接入。