[翻译]-使用 Angular CDK 技术来创建一个消息推送服务(toast service)
原文:Creating a toast service with Angular CDK
作者: Adrian Fâciu
译者: 秋天; 校对者: 尊重
首先,这个 toast 不是祝酒词的意思,而是代表了其他的意思(注:toast service,类似安卓中提供的消息提示推送服务)。做好准备,这篇文章比较长,它将从头开始,讲述一个完备的,可以直接用在生产环境中的消息推送服务。
Angular Material 是优秀的 meterial UI design
的 Angular 实现。CDK (Component Development Kit) 中抽象出了一组实现共同交互的工具,例如 layout、accessibility、grid、tree等。
你可以使用 CDK 来开发自定义组件,在这篇文章中,我们将探讨如何利用 CDK 来创建一个 toast 服务,用来展现整个应用的消息。
安装
首先在项目中增加 CDK 依赖:
yarn add @angular/cdk
或者使用 npm 来安装:
npm install @angular/cdk
现在,我们可以使用 CDK 提供的功能了,本文我们主要使用 overlay 工具,它能够帮助我们在屏幕内部构建可浮动的面板,我们将用它来展示推送的消息。此外,overlay
包中用到了 portal
包,这个包用来控制动态生成内容。
Toast Component
我们首先从基本的内容开始,创建一个组件:
import {
Component } from '@angular/core';
@Component({
selector: 'app-toast',
template: `
<div>This is a toast message</div>
`
})
export class ToastComponent {
}
这可能是最简单的组件了,一个选择器和一个包含有文字信息的 <div>
标签。之后,我们将扩展它以满足我们的需求。当前,我们将专注于在屏幕上显示它。
首先,把组件添加到 NgModule
中,本文的例子中,我们不会直接在模板中使用组件,所以,我们必须在 entryComponents
列表中注册组件,否则编译器会认为它没有被使用,从而不会把它打包进最终的打包文件中。
我们可以像创建一个 Angular 库一样,为 ToastComponent 创建一个 module 文件:
import {
NgModule } from '@angular/core'
import {
ToastComponent } from './toast.component';
@NgModule({
declarations: [ToastComponent],
entryComponents: [ToastComponent]
})
export class ToastModule {
}
对于这个模块,唯一要做的事情,就是在工程的 app.module 的 imports 属性中添加它。
Toast service
现在,我们的消息推送服务已经有了一个组件和模块,我们可以思考接下来要做什么。对于我们的应用,我们需要以编程的方式实现在需要显示推送服务时再显示它。那么,最好的选择就是把这段逻辑写在 service 中:
import {
Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class ToastService {
show() {
}
}
到目前为止,我们有了一个简单的 service,并且包含有一个 show 方法(目暂时这个方法还为空)。唯一需要注意的事情就是,我们在 @Injectable
装饰器中使用了 providedIn
属性(Angular 6 支持),并且指定 root
为它的值。这表明这个 service 将会被注册为一个单例,并且不需要再在 providers
属性中添加这个 service。
这也意味着,这个 service 现在也可以支持摇树优化了,如果我们的应用中定义了一个 service,但是它没有在其他地方被引用,那么它不会被打包到最终的打包文件中。而在 NgModule
中的 providers
选项中注册的 service 则不会被摇树优化。Angular 自身都开始把内置的 service 改为这种方式注册,所以我建议你也可以这样做。
现在,对于我们 ToastService 对 show 方法而言:我们将需要去获取 overylay service 的实例,来创建我们的 toast 组件实例,并可以在屏幕上的任意位置上展示它。
我们可以使用下面三行代码实现这个需求:
const overlayRef = this.overlay.create();
const toastPortal = new ComponentPortal(ToastComponent);
overlayRef.attach(toastPortal);
首先,我们使用 overlay service 中的 create 方法来创建一个 overlay 实例。这将会在应用中创建一个容器,作为我们的消息推送服务的宿主存在,而 create 方法返回的是就是这个容器的引用。
其次,我们需要创建一个 toast 组件的实例,因为我们想要动态地渲染组件,所以我们使用 portal 来实现它。我们从 @angular/cdk/portal
中引入 ComponentPortal 类,并把组件作为参数传递给它。这样就创建了我们组件的实例,并且得到一个可以用来处理它的包装器。
最后,我们需要把 toastPortal
依附到 overlayRef
容器中,这样就可以看到我们的消息推送服务效果了。
现在,如果我们调用 ToastService
中的 show 方法,我们将会发现 div
中的内容被添加到了应用中。然而,它并不像一个浮动的容器或者消息推送通知。好,我们来快速解决这个问题。
overlay
默认使用的位置类(译者注:用于指定容器在窗口中的位置)。因为 CDK 中已经导出了它们,我们可以引入它们,也可以自己自定义。由于我总是赞成重用一些功能,所以,我将直接导入现有的功能。
我们可以在 styles.css
文件中导入 prebuild
css 文件:
@import "~@angular/cdk/overlay-prebuilt.css";
如果我们使用 scss ,我们必须调用 mixin 方法,否则 css 规则会无效:
@import "~@angular/cdk/overlay";
@include cdk-overl