在前面的一篇文章中,介绍了 Angular 框架常用的内置结构指令。我们也可以自定义指令,为 DOM 元素提供高级功能和优雅的外观。
下面我们就动手创建一个自定义的指令,显示动态的版权信息。
生成指令文件
我们可以使用 Angular CLI 的 generate 命令,创建一个指令:
ng generate directive copyright
CREATE src/app/copyright.directive.spec.ts (236 bytes)
CREATE src/app/copyright.directive.ts (147 bytes)
UPDATE src/app/app.module.ts (528 bytes)
Angular CLI 为我们创建了指令文件 copyright.directive.ts
及其单元测试文件 copyright.directive.spec.ts
. 还要注意到,Angular CLI 对 app.module.ts
文件进行了更新,把刚刚创建的指令,添加到主模块的 declarations
属性中,完成了注册。
…
@NgModule({
declarations: [
…
CopyrightDirective
],
imports: [
BrowserModule
],
providers: [
],
bootstrap: [AppComponent]
})
export class AppModule { }
编写指令逻辑
一个指令就是一个装饰了 @Directive
的 TypeScript 类。@Directive
的 selector
属性是必需属性,用来设置指令的选择器。
import { Directive } from '@angular/core’;
@Directive({
selector: '[appCopyright]’
})
export class CopyrightDirective {
constructor() { }
}
指令的选择器(selector)可以是任何有效的 CSS 选择器,与组件的选择器也类似。选择器名称中的 app
是一个前缀,可以在创建 Angular 应用时指定,默认是 app
.
在模板中,可以这样使用 copyright
指令:
<p appCopyright></p>
当然,现在把指令添加到模板上,不会在页面上显示任何内容。接下来,我们就来完成这项工作。
指令的定制逻辑,可以写在指令类的构造函数中:
constructor(el: ElementRef, renderer: Renderer2) {
renderer.addClass(el.nativeElement, 'copyright’);
renderer.setProperty(
el.nativeElement,
‘textContent’,
`©${new Date().getFullYear()} 版权所有`
);
}
我们使用 ElementRef
和 Renderer2
两个类,操作底层的元素。Renderer2
提供了丰富的方法,用于操作 HTML 元素。
-
addClass
,添加样式类到使用指令的 HTML 元素。 -
setProperty
,设置 HTML 元素的textContent
属性,提供实际的版权信息。
ElementRef
和 Renderer2
是 Angular 框架提供的内置类,我们可以直接使用。
编写指令样式
版权信息现在能够展示到页面上了,只是一行普通到文字,没有任何样式。现在,我们给版权内容添加一点样式。
打开 src/styles.css
文件,添加如下内容:
.copyright {
background-color: lightgray;
padding: 10px;
font-family: Verdana, Geneva, Tahoma, sans-serif;
}
注意:我们在这里编辑的是全局样式文件。
页面效果
最后,我们看看版权信息到页面展示效果。
版权信息源代码
src/app/copyright.directive.ts
import { Directive, ElementRef, Renderer2 } from '@angular/core’;
@Directive({
selector: '[appCopyright]’
})
export class CopyrightDirective {
constructor(el: ElementRef, renderer: Renderer2) {
renderer.addClass(el.nativeElement, 'copyright’);
renderer.setProperty(
el.nativeElement,
‘textContent’,
`©${new Date().getFullYear()} 版权所有`
);
}
}
src/app/app.module.ts
import { BrowserModule } from '@angular/platform-browser’;
import { NgModule } from '@angular/core’;
import { AppComponent } from './app.component’;
import { BookComponent } from './book/book.component’;
import { SortPipe } from './sort.pipe’;
import { CopyrightDirective } from './copyright.directive’;
@NgModule({
declarations: [
AppComponent,
BookComponent,
SortPipe,
CopyrightDirective
],
imports: [
BrowserModule
],
providers: [
],
bootstrap: [AppComponent]
})
export class AppModule { }
src/app/app.component.html
<p>{{'hello angular 10' | uppercase}}</p>
<p>{{'HELLO ANGULAR 10' | lowercase}}</p>
<app-book [name]="bookName" (liked)="onLike($event)"></app-book>
<h4>更多图书</h4>
<ul>
<li *ngFor="let book of books | sort:'price'">{{book.name}}</li>
</ul>
<h4>今日推荐</h4>
<div [ngSwitch]=“specialBook”>
<p *ngSwitchCase="'《三体》'">{{specialBook}}</p>
<p *ngSwitchCase="'《超新星纪元》'">{{specialBook}}</p>
<p *ngSwitchCase="'《黑暗森林》'">{{specialBook}}</p>
<p *ngSwitchDefault="'《死神永生》'">{{specialBook}}</p>
</div>
<div appCopyright></div>
src/styles.css
.copyright {
background-color: lightgray;
padding: 10px;
font-family: Verdana, Geneva, Tahoma, sans-serif;
}
网友评论