home
  • 博客
6.11
  • 简介
  • 入门
  • 教程
  • 核心概念
  • 组件
  • 路由
  • 服务
    • 概述
  • EmberData
  • 深入主题
  • 应用程序开发
  • 应用程序关注点
  • 无障碍访问
  • 配置
  • 测试
  • 插件与依赖
  • 使用 TypeScript
  • 开发工具
  • 构建工具
  • Ember Inspector
  • 代码编辑器
  • 其他资源
  • 升级
  • 为 Ember.js 贡献代码
  • 术语表

概述


Service(服务)是一个在整个应用程序生命周期中存在的 Ember 对象,可以在应用程序的不同部分中使用。

服务对于需要共享状态或持久连接的功能非常有用。服务的应用示例可能包括:

  • 用户/会话身份验证。
  • 地理定位。
  • WebSockets。
  • 服务器推送事件或通知。
  • 不适合 EmberData 的服务器后端 API 调用。
  • 第三方 API。
  • 日志记录。

定义服务

可以使用 Ember CLI 的 service 生成器来创建服务。例如,以下命令将创建 ShoppingCart 服务:

ember generate service shopping-cart

服务必须继承 Service 基类。

app/services/shopping-cart.js
import Service from '@ember/service';

export default class ShoppingCartService extends Service {
}

与任何 Ember 对象一样,服务会被初始化,并可以拥有自己的属性和方法。下面,购物车服务管理一个数组,该数组表示购物车中当前包含的项目。

app/services/shopping-cart.js
import Service from '@ember/service';
import { trackedArray } from '@ember/reactive/collections';

export default class ShoppingCartService extends Service {
  items = trackedArray([]);

  add(item) {
    this.items.push(item);
  }

  remove(item) 
    this.items.splice(this.items.indexOf(item), 1);
  }

  empty() {
    this.items.splice(0, this.items.length);
  }
}

访问服务

要访问服务,可以使用 @ember/service 模块中的 service 装饰器将其注入到任何容器解析的对象中,例如组件或其他服务。有两种使用此装饰器的方法:您可以不带参数调用它,也可以向其传递服务的注册名称。当不传递参数时,服务将根据被装饰属性的名称进行加载。您可以像下面这样不带参数加载购物车服务。

app/components/cart-contents.gjs
import Component from '@glimmer/component';
import { service } from '@ember/service';

export default class CartContentsComponent extends Component {
  // Will load the service defined in: app/services/shopping-cart.js
  @service shoppingCart;

  <template>
    <h2>Shopping Cart</h2>
  </template>
}

这会将购物车服务注入到组件中,并使其作为 shoppingCart 属性可用。

注入服务的另一种方法是将服务的名称作为参数传递给装饰器。

app/components/cart-contents.gjs
import Component from '@glimmer/component';
import { service } from '@ember/service';

export default class CartContentsComponent extends Component {
  // Will load the service defined in: app/services/shopping-cart.js
  @service('shopping-cart') cart;

  <template>
    <h2>Shopping Cart</h2>
  </template>
}

这会将购物车服务注入到组件中,并使其作为 cart 属性可用。

有时服务可能存在也可能不存在,例如当初始化器有条件地注册服务时。由于正常的注入在服务不存在时会抛出错误,因此您必须改用 Ember 的 getOwner 来查找该服务。

app/components/cart-contents.gjs
import Component from '@glimmer/component';
import { getOwner } from '@ember/application';

export default class CartContentsComponent extends Component {
  // Will load the service defined in: app/services/shopping-cart.js
  get cart() {
    return getOwner(this).lookup('service:shopping-cart');
  }

  <template>
    <h2>Shopping Cart</h2>
  </template>
}

注入的属性是懒加载的;这意味着除非显式调用该属性,否则不会实例化该服务。

一旦加载,服务将一直持续到应用程序退出。

注入到组件后,服务也可以在模板中使用。

下面我们为 cart-contents 组件添加一个删除操作。

app/components/cart-contents.gjs
import Component from '@glimmer/component';
import { service } from '@ember/service';
import { on } from '@ember/modifier';
import { fn } from '@ember/helper';

export default class CartContentsComponent extends Component {
  @service('shopping-cart') cart;

  remove = (item) => {
    this.cart.remove(item);
  };

  <template>
    <h2>Shopping Cart</h2>
    <ul>
    {{#each this.cart.items as |item|}}
      <li>
        {{item.name}}
        <button type="button" {{on "click" (fn this.remove item)}}>Remove</button>
      </li>
    {{/each}}
    </ul>
  </template>
}
left arrow
控制器
我们已经完成了服务相关内容的介绍。接下来是:EmberData - 简介
right arrow
本页内容

  • 定义服务
  • 访问服务
团队 赞助商 安全 法律条款 品牌形象 社区准则
Twitter GitHub Discord Mastodon

如果你需要帮助,可以通过电子邮件联系我们,提交一个 issue,或者加入 Ember Discord 获取实时帮助。

© 版权所有 2026 - Tilde Inc.
Ember.js 是免费且开源的,并将永远保持免费。


Ember 由以下机构慷慨赞助
Netlify Heroku Fastly Percy Dnsimple