内置指令
Angular 提供了两种内置指令属性型指令和结构型指令
最常见的属性型指令如下:
NgClass —— 添加和删除一组 CSS 类。
NgStyle —— 添加和删除一组 HTML 样式。
NgModel —— 将数据双向绑定添加到 HTML 表单元素。
NgClass 用 ngClass 同时添加或删除几个 CSS 类
1.相关代码
import { Component } from '@angular/core';
@Component({
selector: 'app-built-in-ng-class',
template: `
<h1>app-built-in-ng-class</h1>
/* 绑定单个值, 官方建议用类绑定 */
<h3 [ngClass]="colorRed ? 'color-red' : ''">app-built-in-ng-class</h3>
<br>
<h3 [class.font-size]="isFontSize">app-built-in-ng-class</h3>
<button (click)="colorRed = !colorRed">Change ColorRed Value</button>
<br>
/* 绑定多个值, 官方建议用类绑定*/
<h3 [ngClass]="{'color-red':colorRed,'font-size':isFontSize}">app-built-in-ng-class</h3>
<h3 [ngClass]="isAddClass">app-built-in-ng-class</h3>
`,
styles: [
`
.color-red {
color: red;
}
.font-size {
font-size: 30px;
}
`,
],
})
export class DirectivesBuiltInNgClassComponent {
colorRed: boolean = true;
isFontSize : boolean = true
isAddClass : any = {
'color-red' : true,
'font-size' : true
}
}
NgStyle 使用 NgStyle 根据组件的状态同时动态设置多个内联样式
1.相关代码
import { Component } from '@angular/core';
@Component({
selector: 'app-built-in-ng-style',
template: `
<h1>app-built-in-ng-style</h1>
/* 利用 样式绑定 绑定单个值, 官方建议用样式绑定*/
<h3 [style.color]="colorRed">app-built-in-ng-style</h3>
/* 利用 指令绑定*/
<h3 [ngStyle]="{color:'green'}">app-built-in-ng-style</h3>
/* 绑定多个值, 利用 指令绑定*/
<h3 [ngStyle]="{color:'green',fontSize:'20px'}">app-built-in-ng-style</h3>
<h3 [ngStyle]="ngStyle">app-built-in-ng-style</h3>
`,
})
export class DirectivesBuiltInNgStyleComponent {
colorRed: string = 'red';
ngStyle: any = {
color:"blue",
fontSize : "20px"
};
}
[(ngModel)] :双向绑定 NgModel 指令允许你显示数据属性并在用户进行更改时更新该属性
1.相关代码
import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core';
@Component({
selector: 'app-built-in-ng-model',
template: `
<h1>app-built-in-ng-model</h1>
<h3>{{ inputName }}</h3>
<input [(ngModel)]="inputName" />
<br />
/* (ngModelChange)="inputName = input.value" */
<br />
<input
#input
[ngModel]="inputName"
(ngModelChange)="inputName = input.value"
/>
<br />
/* (ngModelChange)="inputName = $event.target.value" */
<br />
<input
#input
[ngModel]="inputName"
(ngModelChange)="inputName = $event.target.value"
/>
<app-built-in-ng-model-child
[(inputName)]="inputName"
></app-built-in-ng-model-child>
`,
})
export class DirectivesBuiltInNgModelComponent {
private _inputName! : string
get inputName(){
return this._inputName
};
set inputName(value){
console.log('value:', value)
this._inputName = value
}
}
@Component({
selector: 'app-built-in-ng-model-child',
template: `
<h1>app-built-in-ng-model-child</h1>
<h3>{{ inputName }}</h3>
<input #inputChild (input)="change(inputChild.value)" />
`,
})
export class DirectivesBuiltInNgModelChildComponent implements OnInit {
@Input() inputName!: string;
@Output() inputNameChange = new EventEmitter<string>();
ngOnInit() {}
change(value: string) {
this.inputNameChange.emit(value);
}
}
内置结构型指令
NgIf —— 从模板中创建或销毁子视图。
NgFor —— 为列表中的每个条目重复渲染一个节点。
NgSwitch —— 一组在备用视图之间切换的指令。
带 trackBy 的 *ngFor
1.相关代码
/*src/app/app.component.html*/
content_copy
<div *ngFor="let item of items; trackBy: trackByItems">
({{item.id}}) {{item.name}}
</div>
NgSwitch 指令
1.相关代码
/* src/app/app.component.html*/
<div [ngSwitch]="currentItem.feature">
<app-stout-item *ngSwitchCase="'stout'" [item]="currentItem"></app-stout-item>
<app-device-item *ngSwitchCase="'slim'" [item]="currentItem"></app-device-item>
<app-lost-item *ngSwitchCase="'vintage'" [item]="currentItem"></app-lost-item>
<app-best-item *ngSwitchCase="'bright'" [item]="currentItem"></app-best-item>
<app-unknown-item *ngSwitchDefault [item]="currentItem"></app-unknown-item>
</div>
自定义属性指令
1.相关代码
import {
Component,
Directive,
ElementRef,
HostListener,
Input,
} from '@angular/core';
@Directive({
selector: '[appHighlight]',
})
export class HighlightDirective {
el: ElementRef<any>;
/* input属性别名,不然在宿主元素上要绑定两个属性
<p appHighlight [hightColor] = "color">app-hight-directive</p>
*/
@Input('appHighlight') hightColor: string | undefined ;
@Input() defaultColor!: string;
@HostListener('mouseenter') onMouseEnter() {
this.color(this.hightColor || this.defaultColor || 'red');
}
@HostListener('mouseleave') onMouseLeave() {
this.color();
}
@HostListener('click') onClick() {
console.log('22334:', 22334);
}
constructor(el: ElementRef) {
this.el = el;
/* 建议不必要这样做
1.必须正确的书写事件监听器。
2.当指令被销毁的时候,必须拆卸事件监听器,否则会导致内存泄露。
3.必须直接和 DOM API 打交道,应该避免这样做。
*/
// el.nativeElement.onmouseover = function(){
// el.nativeElement.style.color = 'red';
// }
// el.nativeElement.onmouseout = function(){
// el.nativeElement.style.color = '';
// }
}
private color(color: string = '') {
this.el.nativeElement.style.color = color;
}
}
@Component({
selector: 'app-hight-directive',
template: `
<h1>将鼠标移入到文字上</h1>
/* 高亮颜色 和 默认高亮颜色 都不传 */
<p [appHighlight]>app-hight-directive</p>
/* 只传 高亮颜色 */
<p [appHighlight]="color">app-hight-directive</p>
/* 只传 默认高亮颜色 */
<p appHighlight [defaultColor]="defaultColor">app-hight-directive</p>
/ * ngNonBindable 可以让 Angular 不对模板中的表达式进行求值*/
<p ngNonBindable>This should not evaluate: {{ evaluate() }}</p>
<p>This should not evaluate: {{ evaluate() }}</p>
/ * ngNonBindable 可以让 Angular 不对模板中的表达式进行求值
仍然允许指令作用于受 ngNonBindable 影响的元素上*/
<p ngNonBindable [appHighlight]="color">This should not evaluate: {{ evaluate() }}</p>
`,
})
export class HighlightDirectiveComponent {
color: string = 'yellow';
defaultColor: string = 'green';
evaluate() {
return 3 + 4;
}
}
/* 附录:为什么要加@Input?
无论哪种方式,@Input 装饰器都告诉 Angular,该属性是公共的,并且能被父组件绑定。 如果没有 @Input,Angular 就会拒绝绑定到该属性。
但你以前也曾经把模板 HTML 绑定到组件的属性,而且从来没有用过 @Input。 差异何在?
差异在于信任度不同。 Angular 把组件的模板看做从属于该组件的。 组件和它的模板默认会相互信任。 这也就是意味着,组件自己的模板可以绑定到组件的任意属性,无论是否使用了 @Input 装饰器。
但组件或指令不应该盲目的信任其它组件或指令。 因此组件或指令的属性默认是不能被绑定的。 从 Angular 绑定机制的角度来看,它们是私有的,而当添加了 @Input 时,Angular 绑定机制才会把它们当成公共的。 只有这样,它们才能被其它组件或属性绑定。
你可以根据属性名在绑定中出现的位置来判定是否要加 @Input。
当它出现在等号右侧的模板表达式中时,它属于模板所在的组件,不需要 @Input 装饰器。
当它出现在等号左边的方括号([ ])中时,该属性属于其它组件或指令,它必须带有 @Input 装饰器。
试用此原理分析下列范例:
<p [appHighlight]="color">Highlight me!</p>
color 属性位于右侧的绑定表达式中,它属于模板所在的组件。 该模板和组件相互信任。因此 color 不需要 @Input 装饰器。
appHighlight 属性位于左侧,它引用了 HighlightDirective 中一个带别名的属性,它不是模板所属组件的一部分,因此存在信任问题。 所以,该属性必须带 @Input 装饰器。
*/
自定义结构指令
1.相关代码
import { Component, Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[myNgIf]',
})
export class MyNgIfDirective {
@Input('myNgIf') set showFlg(value:boolean){
/* value是绑定的值 templateRef是宿主对象*/
console.log('this.templateRef:', this.templateRef)
if(value){
this.viewContainer.createEmbeddedView(this.templateRef)
}else{
this.viewContainer.clear();
}
};
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef
){}
}
@Component({
selector: 'app-my-ng-if-directive',
template: `
<h1>app-my-ng-if-directive</h1>
<p *myNgIf="show">app-my-ng-if-directive</p>
<button (click)="show = !show">my-ng-if-directive show button</button>
`,
})
export class MyNgIfComponent {
show: boolean = true;
}