Ember.js组件教程:如何编写可复用的HTML优先组件
【免费下载链接】ember.jsEmber.js - A JavaScript framework for creating ambitious web applications项目地址: https://gitcode.com/gh_mirrors/em/ember.js
Ember.js是一个用于构建雄心勃勃的 Web 应用的 JavaScript 框架,而Ember.js 组件正是它最核心的设计哲学——通过可复用的 HTML 优先组件来组织界面。本文将带你从零基础出发,用 5 步学会编写、复用和测试 Ember 组件,让你快速掌握这套 HTML 优先的开发方式。
为什么选择 Ember.js 组件?
Ember.js 把 UI 拆分成一个个独立、可复用的"组件",每个组件 = 一段模板 + (可选)一段行为类。与传统"JS 优先"的写法不同,Ember 的组件是HTML 优先的:你先写模板(长什么样),需要时再添加类(怎么工作)。
Ember 提供了三种组件写法,新手可以按场景选择:
| 组件类型 | 导入来源 | 适用场景 |
|---|---|---|
| 模板组件(Template-only) | @ember/component/template-only | 纯展示、无逻辑的 UI,如卡片、列表项 |
| Glimmer 组件 | @glimmer/component | 需要状态、计算属性、生命周期逻辑 |
| Classic 组件 | @ember/component | 维护老项目,新项目不推荐 |
💡核心建议:默认优先使用模板组件或 Glimmer 组件。它们的源码分别位于 template-only.ts 和 packages/@glimmer/component/src/index.ts,官方文档就写在这些模块里。
第一步:一键生成新组件
最快的创建方式是使用ember generate命令,模板文件由项目内的 blueprints/component/index.js 蓝图自动生成:
# 创建纯模板组件(推荐新手起点) ember generate component user-card --no-component-class # 创建带类行为的 Glimmer 组件 ember generate component user-card --component-class @glimmer/component生成后你会在app/components/目录下看到新组件。默认格式是.gjs的 template tag 文件(自 Ember 6.8 起成为默认格式),其原始模板见templatename.gjs:
<template> {{yield}} </template>命名约定很简单:文件名用短横线(user-card.gjs),模板中调用时大写首字母(<UserCard />),以此区分普通 HTML 标签。
第二步:编写 HTML 优先的模板组件
"HTML 优先"意味着:组件的核心就是一段真实 HTML,参数通过@前缀传入。例如一个纯模板的用户卡片:
// app/components/user-card.gjs <template> <div class="card"> <img src={{@user.avatar}} alt="{{@user.name}}"> <h3>{{@user.name}}</h3> <p>{{@user.bio}}</p> </div> </template>在其他地方调用它,就像使用 HTML 标签一样自然:
<UserCard @user={{@model.currentUser}} />模板组件没有类实例,模板中只能访问传入的参数(@arg),这使它极轻量——渲染引擎还能跳过多余的包装元素,直接输出"外层 HTML"。这一优化的说明写在 template-only.ts 的模块文档中。
第三步:用块(Block)让组件更灵活
当组件需要接受"自定义内容"时,用{{yield}}开一个插槽:
<template> <article class="post"> <h2>{{yield to="title"}}</h2> {{yield}} </article> </template>调用时可以传入命名块,像拼图一样把内容嵌进指定位置:
<Post> <:title>我的第一篇文章</:title> <p>这里是正文……</p> </Post>进阶技巧:
- ✅ 用
(has-block "title")检查某个块是否存在,不存在时提供默认内容 - ✅ 用
{{yield @user.name}}把值传递给块,接收方用as |name|接住 - ✅ 所有命名块都必须显式命名,未命名的内容默认是
:default块
第四步:给组件添加 JavaScript 行为
需要逻辑时,在同一个.gjs文件里加一个继承自@glimmer/component的类,模板包在类里面——一个文件搞定:
// app/components/user-card.gjs import Component from '@glimmer/component'; export default class UserCard extends Component { get displayName() { return `${this.args.user.firstName} ${this.args.user.lastName}`; } <template> <h3>{{this.displayName}}</h3> {{yield}} </template> }Glimmer 组件的常用 API 速查(完整文档见 packages/@glimmer/component/src/index.ts):
this.args—— 所有传入参数的集合,自动具备响应式追踪constructor(owner, args)—— 初始化状态;服务注入与参数在此就已可用willDestroy()—— 组件移出 DOM 后清理定时器、订阅等资源this—— 在模板中引用类实例,访问属性与方法
第五步:为组件编写测试
组件可复用,更要可信赖。用ember generate component-test生成测试文件(由 blueprints/component-test/ 蓝图提供),只需渲染组件、传入参数、断言结果:
test('it renders the user name', async function (assert) { await render(<UserCard @user={{this.user}} />); assert.dom('.card h3').hasText('Alice Smith'); });测试模板同样支持.gjs格式,与组件写法保持一致。
最佳实践清单 🧭
- 默认从模板组件开始,确实需要逻辑再升级为 Glimmer 组件,避免过度设计
- 组件放
app/components/,路由页面组件放app/templates/并与路由同名 - 参数命名用业务语义(
@user、@fadeIn),少用@value、@data这类模糊命名 willDestroy中释放一切外部资源(定时器、事件订阅、动画注册)- 模板与类同文件(
.gjs),保持组件自包含、易迁移
相关源码导航
| 模块 | 说明 |
|---|---|
| packages/@glimmer/component/src/index.ts | Glimmer 组件核心类与完整 API 文档 |
| packages/@ember/component/index.ts | 组件公开 API:模板绑定、管理器注册 |
| packages/@ember/component/template-only.ts | 模板组件声明与渲染优化说明 |
| blueprints/component/index.js | ember generate component的生成逻辑 |
| blueprints/component-test/ | 组件测试文件生成蓝图 |
掌握以上五步,你已经在用 Ember.js 最地道的 HTML 优先方式构建可复用组件了。从小的展示组件开始,逐步加入块插槽与类逻辑,你的代码库会越来越像积木一样清晰、好维护。
【免费下载链接】ember.jsEmber.js - A JavaScript framework for creating ambitious web applications项目地址: https://gitcode.com/gh_mirrors/em/ember.js
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考