Ember模板语法 #
一、条件渲染 #
1.1 if/else #
handlebars
{{! 基本if}}
{{#if this.isLoggedIn}}
<p>欢迎回来!</p>
{{/if}}
{{! if/else}}
{{#if this.isLoggedIn}}
<p>欢迎回来!</p>
{{else}}
<p>请先登录</p>
{{/if}}
{{! if/else if/else}}
{{#if this.isAdmin}}
<p>管理员面板</p>
{{else if this.isEditor}}
<p>编辑者面板</p>
{{else}}
<p>用户面板</p>
{{/if}}
1.2 unless #
handlebars
{{! unless - if的反向}}
{{#unless this.isPublished}}
<span class="draft">草稿</span>
{{/unless}}
{{! 等价于}}
{{#if (not this.isPublished)}}
<span class="draft">草稿</span>
{{/if}}
1.3 内联if #
handlebars
{{! 内联if助手}}
<span class="status">{{if this.isActive "激活" "未激活"}}</span>
{{! 只有两个参数时}}
<span>{{if this.hasError "错误"}}</span>
1.4 复杂条件 #
handlebars
{{! 使用and/or/not助手}}
{{#if (and this.isLoggedIn this.hasPermission)}}
<p>可以访问</p>
{{/if}}
{{#if (or this.isAdmin this.isEditor)}}
<p>管理权限</p>
{{/if}}
{{#if (not this.isBanned)}}
<p>正常用户</p>
{{/if}}
{{! 使用eq助手}}
{{#if (eq this.status "active")}}
<span class="active">活跃</span>
{{/if}}
二、循环渲染 #
2.1 each基本用法 #
handlebars
<ul>
{{#each @model as |post|}}
<li>{{post.title}}</li>
{{/each}}
</ul>
2.2 each with index #
handlebars
<ol>
{{#each @model as |post index|}}
<li>
<span class="number">{{index}}</span>
{{post.title}}
</li>
{{/each}}
</ol>
2.3 each with else #
handlebars
<ul>
{{#each @model as |post|}}
<li>{{post.title}}</li>
{{else}}
<li class="empty">暂无文章</li>
{{/each}}
</ul>
2.4 each-in #
handlebars
{{! 遍历对象}}
<dl>
{{#each-in this.user as |key value|}}
<dt>{{key}}</dt>
<dd>{{value}}</dd>
{{/each-in}}
</dl>
2.5 嵌套循环 #
handlebars
{{#each @categories as |category|}}
<div class="category">
<h2>{{category.name}}</h2>
<ul>
{{#each category.items as |item|}}
<li>{{item.name}}</li>
{{/each}}
</ul>
</div>
{{/each}}
三、动态属性 #
3.1 动态class #
handlebars
{{! 条件class}}
<div class="card {{if this.isActive "active"}}">
内容
</div>
{{! 多条件class}}
<div class="btn {{this.size}} {{this.type}} {{if this.disabled "disabled"}}">
按钮
</div>
{{! 使用concat}}
<div class="{{concat "alert-" this.type}}">
提示信息
</div>
3.2 动态属性 #
handlebars
{{! 动态属性值}}
<input type="text" value={{this.inputValue}} />
{{! 动态属性名}}
<div {{prop this.attrName this.attrValue}}></div>
{{! 布尔属性}}
<input type="checkbox" checked={{this.isChecked}} />
<button disabled={{this.isDisabled}}>提交</button>
3.3 动态style #
handlebars
{{! 内联style}}
<div style="color: {{this.color}}; background: {{this.bgColor}}">
内容
</div>
{{! 使用html-safe}}
<div style={{this.computedStyle}}>内容</div>
javascript
import { htmlSafe } from '@ember/template';
get computedStyle() {
return htmlSafe(`color: ${this.color}; font-size: ${this.fontSize}px`);
}
四、模板组合 #
4.1 yield产出 #
handlebars
{{! 父模板}}
<Card @title="用户信息">
<p>姓名:{{@user.name}}</p>
<p>邮箱:{{@user.email}}</p>
</Card>
{{! Card组件}}
<div class="card">
<div class="card-header">
<h3>{{@title}}</h3>
</div>
<div class="card-body">
{{yield}}
</div>
</div>
4.2 块参数 #
handlebars
{{! 父模板}}
<DataTable @data={{@users} as |row|>
<td>{{row.name}}</td>
<td>{{row.email}}</td>
<td>{{row.role}}</td>
</DataTable>
{{! DataTable组件}}
<table>
<tbody>
{{#each @data as |row|}}
<tr>
{{yield row}}
</tr>
{{/each}}
</tbody>
</table>
4.3 多个yield #
handlebars
{{! 父模板}}
<Layout>
<:header>
<h1>页面标题</h1>
</:header>
<:main>
<p>主要内容</p>
</:main>
<:footer>
<p>页脚信息</p>
</:footer>
</Layout>
{{! Layout组件}}
<div class="layout">
<header class="header">
{{yield to="header"}}
</header>
<main class="main">
{{yield to="main"}}
</main>
<footer class="footer">
{{yield to="footer"}}
</footer>
</div>
五、模板引用 #
5.1 基本引用 #
handlebars
<div {{ref "myDiv"}}>
内容
</div>
<button {{on "click" (fn this.scrollTo "myDiv")}}>
滚动到内容
</button>
javascript
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
export default class MyComponent extends Component {
@tracked refs = {};
@action
scrollTo(refName) {
const element = this.refs[refName];
element?.scrollIntoView({ behavior: 'smooth' });
}
}
六、模板助手 #
6.1 内置助手 #
handlebars
{{! 数组助手}}
{{#each (array "a" "b" "c") as |item|}}
{{item}}
{{/each}}
{{! 对象助手}}
{{#let (hash name="张三" age=25) as |user|}}
{{user.name}}
{{/let}}
{{! 字符串拼接}}
{{concat "Hello" " " "World"}}
{{! 动态获取}}
{{get this.user this.fieldName}}
6.2 数学助手 #
handlebars
{{! 加法}}
{{add 1 2}}
{{! 减法}}
{{sub 10 3}}
{{! 乘法}}
{{mul 4 5}}
{{! 除法}}
{{div 20 4}}
{{! 取模}}
{{mod 10 3}}
6.3 比较助手 #
handlebars
{{! 等于}}
{{eq this.value "expected"}}
{{! 不等于}}
{{not-eq this.value "unexpected"}}
{{! 大于/小于}}
{{gt this.age 18}}
{{gte this.age 18}}
{{lt this.age 60}}
{{lte this.age 60}}
七、表单处理 #
7.1 Input组件 #
handlebars
{{! 文本输入}}
<Input
@type="text"
@value={{this.name}}
placeholder="请输入姓名"
{{on "input" this.validateName}}
/>
{{! 密码输入}}
<Input @type="password" @value={{this.password}} />
{{! 邮箱输入}}
<Input @type="email" @value={{this.email}} />
{{! 数字输入}}
<Input @type="number" @value={{this.age}} min="0" max="150" />
7.2 复选框和单选 #
handlebars
{{! 复选框}}
<label>
<Input @type="checkbox" @checked={{this.agree}} />
同意条款
</label>
{{! 单选按钮组}}
{{#each this.options as |option|}}
<label>
<Input
@type="radio"
@name="gender"
@value={{option.value}}
@checked={{eq this.selected option.value}}
/>
{{option.label}}
</label>
{{/each}}
7.3 选择框 #
handlebars
<select {{on "change" this.handleChange}}>
<option value="">请选择</option>
{{#each this.options as |option|}}
<option value={{option.value}} selected={{eq this.selected option.value}}>
{{option.label}}
</option>
{{/each}}
</select>
7.4 Textarea #
handlebars
<Textarea
@value={{this.content}}
rows="5"
placeholder="请输入内容"
{{on "input" this.countCharacters}}
/>
<p>已输入 {{this.charCount}} 字符</p>
八、链接与导航 #
8.1 LinkTo #
handlebars
{{! 基本链接}}
<LinkTo @route="home">首页</LinkTo>
{{! 带模型参数}}
<LinkTo @route="posts.show" @model={{@post.id}}>
查看文章
</LinkTo>
{{! 带查询参数}}
<LinkTo @route="posts" @query={{hash page=1 sort="date"}}>
文章列表
</LinkTo>
{{! 禁用链接}}
<LinkTo @route="home" @disabled={{true}}>禁用链接</LinkTo>
{{! 替换历史记录}}
<LinkTo @route="home" @replace={{true}}>首页</LinkTo>
8.2 动态链接 #
handlebars
{{! 动态路由名}}
<LinkTo @route={{this.currentRoute}}>当前页面</LinkTo>
{{! 条件链接}}
{{#if this.canEdit}}
<LinkTo @route="posts.edit" @model={{@post.id}}>编辑</LinkTo>
{{else}}
<span class="disabled">无权限编辑</span>
{{/if}}
九、异步模板 #
9.1 处理Promise #
handlebars
{{! Ember自动处理Promise}}
{{#each @model as |post|}}
{{! 数据加载完成后渲染}}
<p>{{post.title}}</p>
{{/each}}
9.2 加载状态 #
handlebars
{{#if this.isLoading}}
<div class="loading">加载中...</div>
{{else}}
{{! 显示内容}}
{{/if}}
十、模板调试 #
10.1 log助手 #
handlebars
{{! 输出到控制台}}
{{log "调试信息:" this.user}}
{{! 输出多个值}}
{{log "用户:" this.user "状态:" this.status}}
10.2 debugger #
handlebars
{{! 断点调试}}
{{debugger}}
{{! 条件断点}}
{{#if this.hasError}}
{{debugger}}
{{/if}}
十一、模板性能优化 #
11.1 避免重复计算 #
handlebars
{{! 不推荐 - 重复计算}}
<p>{{format-date @post.createdAt}}</p>
<small>{{format-date @post.createdAt}}</small>
{{! 推荐 - 使用let}}
{{#let (format-date @post.createdAt) as |date|}}
<p>{{date}}</p>
<small>{{date}}</small>
{{/let}}
11.2 合理使用组件 #
handlebars
{{! 不推荐 - 复杂模板}}
<ul>
{{#each @items as |item|}}
<li class="item {{if item.active "active"}}">
<span class="name">{{item.name}}</span>
<span class="price">{{item.price}}</span>
{{! 更多复杂结构...}}
</li>
{{/each}}
</ul>
{{! 推荐 - 组件化}}
<ul>
{{#each @items as |item|}}
<ItemRow @item={{item}} />
{{/each}}
</ul>
十二、总结 #
Ember模板语法要点:
| 语法 | 用途 |
|---|---|
{{#if}} |
条件渲染 |
{{#each}} |
循环渲染 |
{{on}} |
事件绑定 |
{{yield}} |
内容产出 |
<LinkTo> |
路由链接 |
<Input> |
表单输入 |
{{let}} |
变量定义 |
{{log}} |
调试输出 |
掌握这些模板语法,可以构建灵活、高效的Ember应用界面。
最后更新:2026-03-28