简单来说,就是把"骨架(HTML)"和"血肉(Mock数据/真实数据)"完全分开存放。底层确实就是两个独立的文件(或两份独立的代码资源),只有在最后展示的那一瞬间,才会通过代码把它们"组装"起来。
为了让你更直观地理解这套机制,我们可以把它拆解为三个步骤:
1. 准备"骨架":HTML 模板文件 (template.html)
在这个文件里,你只需要关心界面长什么样,并在需要动态替换的地方留好"坑位"(比如使用 {``{变量名}} 或特定的 class 名)。
<!-- template.html -->
<div class="transfer-card">
<div class="card-header">💸 转账通知</div>
<div class="card-body">
<p>付款人:<span class="payer-name">{{payer_name}}</span></p>
<p>收款人:<span class="payee-name">{{payee_name}}</span></p>
<p>转账金额:<span class="amount">{{amount}}</span></p>
</div>
</div>
2. 准备"血肉":Mock 数据文件 (mock.json)
在这个文件里,存放你用来预览的示例数据。它和 HTML 模板互不干扰,你可以随时修改数据来测试不同的展示效果。
// mock.json
{
"payer_name": "张三",
"payee_name": "李四",
"amount": "10块钱"
}
3. 组装渲染:解析器 (JavaScript)
在前端运行时(或者在构建阶段),写一段简单的 JS 代码,把这两个文件读取出来,用 JSON 里的数据去替换 HTML 里的"坑位",最后把组装好的内容放到页面上。
// 1. 获取 HTML 模板字符串(实际开发中可以通过 fetch 读取 template.html 文件)
const templateHTML = document.getElementById('template-container').innerHTML;
// 2. 获取 Mock 数据(实际开发中可以通过 fetch 读取 mock.json 文件)
const mockData = {
payer_name: "张三",
payee_name: "李四",
amount: "10块钱"
};
// 3. 核心替换逻辑(简单的模板引擎)
function renderTemplate(template, data) {
return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
return data[key] || match; // 如果数据里有值就替换,没有就保留原样
});
}
// 4. 执行替换并展示
const finalHTML = renderTemplate(templateHTML, mockData);
document.getElementById('app').innerHTML = finalHTML;
这种"两文件分离"模式的好处:
- 预览与真实无缝切换 :当你需要预览时,前端加载
mock.json;当智能体上线后,前端只需要把mock.json换成大模型返回的真实 JSON 数据,HTML 模板文件完全不需要做任何修改。 - 前后端/设计与开发彻底解耦:写 HTML/CSS 的人只需要关注界面好不好看,写数据的人(或大模型)只需要保证 JSON 字段名对得上。大家互不干扰,并行开发。
- 安全且易维护:这种模式其实就是你之前问的 DSL 的底层变种。它避免了直接拼接 HTML 字符串带来的安全风险(XSS),同时也让代码结构非常清晰。
- 也可以使用DSL json组件,前端针对这类开发一个卡片功能通过DSLRenderer去渲染返回出去,需要窗口展示做组件适配:例如定制统一的返回接口
{"type":"text","context":"内容"} {"type":"dsl","context":"内容"}