AppML 案例模板
自定义列表与表单的 HTML 结构,用占位符绑定数据。
Key Points模板就是带 {{字段名}} 占位符的 HTML 片段,AppML 按数据逐条替换后插入页面。
默认渲染 vs 模板
| Template | ||
|---|---|---|
| Markup | 框架生成的表格 | 你写的 HTML |
| Styling | 受限于默认类名 | 完全自由 |
| Fields | 按 items 全列 | 想显示哪些就写哪些 |
| Cost | 零成本 | 要维护模板 |
卡片式列表
HTML
<appml-app src="models/customers.xml">
<appml-template view="list">
<div class="card">
<h3>{{company}}</h3>
<p class="contact">{{contact}} · {{city}}</p>
<p class="credit">额度:{{credit}}</p>
</div>
</appml-template>
</appml-app>CSS
.card {
border: 1px solid #e5e7eb;
border-radius: .5rem;
padding: 1rem 1.2rem;
margin-bottom: .8rem;
background: #fff;
box-shadow: 0 1px 2px rgba(0,0,0,.04);
}
.card h3 { margin: 0 0 .3rem; font-size: 1.05rem; }
.card .contact { color: #6b7280; margin: 0 0 .4rem; font-size: .9rem; }
.card .credit { margin: 0; font-weight: 600; color: #047857; }Output
北京云图科技
张伟 · 北京
额度:50000
上海海联贸易
李娜 · 上海
额度:80000占位符规则
- **
{{字段名}}** —— 替换成该字段的值 - 不存在的字段 —— 替换成空串,不报错
- 原样插入 HTML —— 值不会被转义,注意 XSS
Placeholder substitution usually does not escape HTML. A
<script> in user data becomes a live tag. Sanitise before display, or escape server-side before storing.表单模板
HTML
<appml-app src="models/customers.xml">
<appml-template view="form">
<div class="field">
<label>公司名称</label>
<input name="company" value="{{company}}" required>
</div>
<div class="field">
<label>联系人</label>
<input name="contact" value="{{contact}}">
</div>
<div class="field">
<label>城市</label>
<input name="city" value="{{city}}">
</div>
<div class="field">
<label>额度</label>
<input name="credit" type="number" value="{{credit}}">
</div>
</appml-template>
</appml-app>In a form template the name attribute must match item name; that is how the framework maps values back. name="companyName" silently fails to save.
条件与格式化
HTML
<div class="card">
<h3>{{name}}</h3>
<p>库存:{{stock}}</p>
<p class="tag">{{category}}</p>
</div>Templates support neither conditionals nor loops. For "red when stock is 0" or thousands separators, pre-process in the controller or post-process the DOM with JS.
JavaScript
function productsController(appml) {
appml.onload = function () {
document.querySelectorAll('.card').forEach((card) => {
const stock = card.querySelector('p:nth-of-type(1)');
if (stock && stock.textContent.trim() === '库存:0') {
card.style.borderColor = '#dc2626';
}
});
};
}Post-processing in onload works but is fragile because it depends on template structure. With many fields, rendering yourself from appml.data is more robust.
什么时候值得写模板
- 卡片列表 —— 表格放不下的多行信息
- 品牌化界面 —— 要贴合现有设计系统
- 不写 —— 内部工具、字段少、只要能用
默认渲染 vs 模板
| Default | 模板 | |
|---|---|---|
| 结构 | 框架生成的表格 | 你写的 HTML |
| 样式 | 受限于默认类名 | 完全自由 |
| 字段 | 按 items 全列 | 想显示哪些就写哪些 |
| 代价 | 零成本 | 要维护模板 |
卡片式列表
HTML
<appml-app src="models/customers.xml">
<appml-template view="list">
<div class="card">
<h3>{{company}}</h3>
<p class="contact">{{contact}} · {{city}}</p>
<p class="credit">额度:{{credit}}</p>
</div>
</appml-template>
</appml-app>CSS
.card {
border: 1px solid #e5e7eb;
border-radius: .5rem;
padding: 1rem 1.2rem;
margin-bottom: .8rem;
background: #fff;
box-shadow: 0 1px 2px rgba(0,0,0,.04);
}
.card h3 { margin: 0 0 .3rem; font-size: 1.05rem; }
.card .contact { color: #6b7280; margin: 0 0 .4rem; font-size: .9rem; }
.card .credit { margin: 0; font-weight: 600; color: #047857; }Output
北京云图科技
张伟 · 北京
额度:50000
上海海联贸易
李娜 · 上海
额度:80000占位符规则
- **
{{字段名}}** —— 替换成该字段的值 - 不存在的字段 —— 替换成空串,不报错
- 原样插入 HTML —— 值不会被转义,注意 XSS
占位符替换通常不做 HTML 转义。如果数据里含有用户输入的
<script>,会被当成标签执行。展示用户内容前必须自己清洗,或在服务端就转义好再存。表单模板
HTML
<appml-app src="models/customers.xml">
<appml-template view="form">
<div class="field">
<label>公司名称</label>
<input name="company" value="{{company}}" required>
</div>
<div class="field">
<label>联系人</label>
<input name="contact" value="{{contact}}">
</div>
<div class="field">
<label>城市</label>
<input name="city" value="{{city}}">
</div>
<div class="field">
<label>额度</label>
<input name="credit" type="number" value="{{credit}}">
</div>
</appml-template>
</appml-app>表单模板里 name 属性必须与 item name 一致,框架靠它把值回填到当前记录。写成 name="companyName" 就保存不上——而且不会提示。
条件与格式化
HTML
<div class="card">
<h3>{{name}}</h3>
<p>库存:{{stock}}</p>
<p class="tag">{{category}}</p>
</div>模板本身不支持条件判断和循环。要做「库存为 0 时显示红色」「金额千分位」这类逻辑,得在控制器里预处理数据,或渲染后用 JS 二次加工 DOM。
JavaScript
function productsController(appml) {
appml.onload = function () {
document.querySelectorAll('.card').forEach((card) => {
const stock = card.querySelector('p:nth-of-type(1)');
if (stock && stock.textContent.trim() === '库存:0') {
card.style.borderColor = '#dc2626';
}
});
};
}用 onload 之后再改 DOM 是可行但脆弱的做法——依赖模板结构。字段多了以后,更稳的方式是自己用 appml.data 渲染,完全绕开模板。
什么时候值得写模板
- 卡片列表 —— 表格放不下的多行信息
- 品牌化界面 —— 要贴合现有设计系统
- 不写 —— 内部工具、字段少、只要能用