Angular 是一款流行的前端框架,它具有模块化、可重用性和可维护性等优点。在 Angular 中,组件是应用程序的基本构建块。本文将介绍如何使用 Angular 编写可重用性组件的技巧,包括模板、样式、输入输出和依赖注入等方面的内容。
模板
模板是 Angular 组件的视图,它定义了组件的 HTML 结构和数据绑定。编写可重用性组件时,需要考虑以下几点:
使用模板引用变量:模板引用变量是组件内部的变量,可以在模板中引用。例如:
<input #nameInput type="text"> <button (click)="submit(nameInput.value)">Submit</button>
在上面的例子中,
#nameInput定义了一个模板引用变量,可以在submit方法中引用该变量的值。使用 ng-content:ng-content 是 Angular 提供的一种内容投影机制,可以将组件的内容插入到组件的模板中。例如:
<div class="card"> <div class="card-header"> <ng-content select=".card-header"></ng-content> </div> <div class="card-body"> <ng-content select=".card-body"></ng-content> </div> </div>在上面的例子中,使用了 ng-content 投影了两个 CSS 选择器
.card-header和.card-body,可以将这两个选择器所包含的内容插入到组件的模板中。使用 ng-template:ng-template 是 Angular 提供的一种模板定义机制,可以定义一个模板,并在需要的时候进行渲染。例如:
<ng-template #myTemplate let-name="name"> <div>Hello, {{name}}!</div> </ng-template> <ng-container *ngTemplateOutlet="myTemplate; context: {$implicit: 'John'}"></ng-container>在上面的例子中,定义了一个 ng-template,并将其赋值给了
#myTemplate。在 ng-container 中使用了*ngTemplateOutlet将该模板渲染出来,同时传递了一个名为name的参数。
样式
样式是 Angular 组件的外观,可以使用 CSS 或 SCSS 编写。编写可重用性组件时,需要考虑以下几点:
使用 :host 和 :host-context::host 和 :host-context 是 Angular 提供的两种样式伪类,可以控制组件自身和其宿主元素的样式。例如:
// www.javascriptcn.com code example :host { display: block; border: 1px solid #ccc; padding: 10px; } :host-context(.dark-theme) { background-color: #333; color: #fff; }在上面的例子中,:host 控制了组件自身的样式,:host-context 控制了宿主元素的样式。
使用 :ng-deep::ng-deep 是 Angular 提供的样式穿透机制,可以将样式应用到组件的子元素中。例如:
// www.javascriptcn.com code example :host { display: block; // 使用 :ng-deep 将样式应用到子元素中 ::ng-deep .list-item { font-size: 14px; color: #333; } }在上面的例子中,使用 :ng-deep 将样式应用到了
.list-item子元素中。
输入输出
输入和输出是 Angular 组件的两种属性,用于与父组件或子组件进行通信。编写可重用性组件时,需要考虑以下几点:
使用 @Input 和 @Output 装饰器:@Input 和 @Output 是 Angular 提供的装饰器,用于定义输入和输出属性。例如:
// www.javascriptcn.com code example @Component({ selector: 'app-user', template: ` <div> <h2>{{name}}</h2> <button (click)="onClick()">Click me</button> </div> ` }) export class UserComponent { @Input() name: string; @Output() clicked = new EventEmitter<void>(); onClick() { this.clicked.emit(); } }在上面的例子中,使用了 @Input 装饰器定义了一个名为
name的输入属性,使用了 @Output 装饰器定义了一个名为clicked的输出属性,并在onClick方法中触发了该属性。使用 ng-content 和 @ContentChild:ng-content 可以将父组件传递的内容插入到子组件中,@ContentChild 可以获取子组件中的 ng-content。例如:
<app-user> <div class="message">Hello, world!</div> </app-user>
// www.javascriptcn.com code example @Component({ selector: 'app-user', template: ` <div> <ng-content></ng-content> </div> ` }) export class UserComponent implements AfterContentInit { @ContentChild('.message') message: ElementRef; ngAfterContentInit() { console.log(this.message.nativeElement.textContent); // 输出 Hello, world! } }在上面的例子中,使用了 ng-content 将父组件传递的内容插入到子组件中,并使用了 @ContentChild 获取了子组件中的
.message元素。
依赖注入
依赖注入是 Angular 的核心特性之一,它可以将组件所需的服务注入到组件中。编写可重用性组件时,需要考虑以下几点:
使用 @Injectable 和 providedIn:@Injectable 是 Angular 提供的服务装饰器,用于定义服务类。providedIn 是 @Injectable 的一个选项,用于指定服务的提供者。例如:
@Injectable({ providedIn: 'root' }) export class UserService { getUsers() { return ['Alice', 'Bob', 'Charlie']; } }在上面的例子中,定义了一个名为
UserService的服务,并将其提供给了整个应用程序。使用 @Inject 和 DI:@Inject 是 Angular 提供的依赖注入装饰器,用于将服务注入到组件中。DI(Dependency Injection)则是 Angular 提供的依赖注入机制。例如:
// www.javascriptcn.com code example @Component({ selector: 'app-user-list', template: ` <ul> <li *ngFor="let user of users">{{user}}</li> </ul> ` }) export class UserListComponent { users: string[]; constructor(@Inject(UserService) private userService: UserService) { this.users = this.userService.getUsers(); } }在上面的例子中,使用了 @Inject 将
UserService服务注入到了组件中,并在构造函数中使用了 DI 获取了该服务的实例。
示例代码
下面是一个使用 Angular 编写可重用性组件的示例代码:
// www.javascriptcn.com code example
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-counter',
template: `
<div>
<button (click)="decrement()">-</button>
<span>{{count}}</span>
<button (click)="increment()">+</button>
</div>
`,
styles: [`
div {
display: flex;
align-items: center;
}
button {
padding: 5px;
margin: 0 5px;
border: none;
border-radius: 3px;
background-color: #eee;
cursor: pointer;
}
`]
})
export class CounterComponent {
@Input() count = 0;
@Output() countChanged = new EventEmitter<number>();
increment() {
this.count++;
this.countChanged.emit(this.count);
}
decrement() {
this.count--;
this.countChanged.emit(this.count);
}
}在上面的例子中,定义了一个名为 CounterComponent 的组件,包含了一个名为 count 的输入属性和一个名为 countChanged 的输出属性。组件的模板中包含了两个按钮,分别用于增加和减少计数器的值。组件的样式中定义了按钮的样式。
Source: FunTeaLearn,Please indicate the source for reprints https://funteas.com/post/67da27bca941bf71341e3412