在视图中使用的属性值为 null or undefined 时,javascript 和 angular 会引发空指针异常并中断视图的渲染过程, 从而视图会渲染失败,而使用了安全导航运算符(?)后,视图依然会渲染,只是显示的值为空白
<h3>5.2、安全导航运算符</h3> <p>第五个专案的名称为:{{products[5].name}}</p> <p>第五个专案的名称为:{{products[5]?.name}}</p>
非空断言运算符
在 tsconfig.json 中启用 strictNullChecks 属性,typescript 将会强制开启严格的空值检查,在这种模式下,所有定义了类型的属性是不允许赋值为 null 的,当将属性赋值为 null,则会编译报错
非空断言运算符用来告诉编译器对特定的属性不做严格的空值校验,当属性值为 null or undefined 时,不抛错误。在下面的代码中,在判断 obj 存在后,就不再针对 obj.name 进行校验
import { Component, OnInit } from '@angular/core'; interface Person { name: string; age: number; } @Component({ selector: 'app-product-list', templateUrl: './product-list.component.html', styleUrls: ['./product-list.component.scss'] }) export class ProductListComponent implements OnInit { public obj: Person; constructor() { } ngOnInit(): void { } } <p *ngIf="obj"> <span>{{obj!.name}}</span> </p>非空断言运算符不会防止出现 null 或 undefined,只是不提示
4.3.2、常用的管道函数
纯管道
只有在它检测到输入值发生了纯变更时才会执行,但是会忽略对象内部的变更
纯变更是指对原始类型值(String、Number、Boolean、Symbol)的更改, 或者对对象引用(Date、Array、Function、Object)的更改
非纯管道
每个组件的变更周期都会执行
管道 作用JsonPipe 将一个值转换成 json 字符串
DatePipe 根据区域设置规则格式化日期值
UpperCasePipe 把文本转换成全大写形式
LowerCasePipe 把文本转换成全小写形式
<h3>6.1、json 管道</h3> <p>{{products | json}}</p> <h3>6.2、date 管道</h3> <p>现在时间:{{date | date:'yyyy-MM-dd HH:mm:ss'}}</p> <h3>6.3、upper 管道</h3> <p>转换成全大写:{{url | uppercase}}</p> <h3>6.4、lower 管道</h3> <p>转换成全小写:{{url | lowercase}}</p> 4.4、组件之间的通信 4.4.1、输入属性与输出属性
输入属性(@Input)和输出属性(@Output)用来在父子组件或指令中进行共享数据。@Input 用来获取数据,@Output 用来向外发送数据
4.4.2、子组件获取父组件信息
在父组件中,添加对于子组件的引用,并将需要传递的数据 or 方法绑定到子组件上
传递数据直接将父组件中的属性值赋值给绑定在子组件上的属性就可以了
传递方法时,绑定在子组件上的属性是父组件方法的名称,此处不能加 () ,否则就会直接执行该父组件的方法
在传递数据给子组件时,也可以通过 this 来指代父组件,从而将整个父组件作为数据绑定子组件上
<h2>父组件内容:</h2> <p> <label for="title">标题:</label> <input type="text" [(ngModel)]="title"> </p> <hr> <h2>子组件内容:</h2> <!-- 将父组件的数据绑定到子组件上 --> <app-child-component [parentTitle]="title" [parentGetMsg]='getMsg'></app-child-component>
在子组件中引入 Inupt,同时使用 @Input 装饰器来接收父组件传递的数据
// 引入 Input 接口 import { Component, OnInit, Input } from '@angular/core'; @Component({ selector: 'app-child-component', templateUrl: './child-component.component.html', styleUrls: ['./child-component.component.scss'] }) export class ChildComponentComponent implements OnInit { // 获取父组件的数据 @Input() parentGetMsg: any; // 使用 setter 对父组件的数据进行深加工 private _title: string; @Input() set parentTitle(title: string) { this._title = (title && title.trim()) || '父组件的 title 属性值为空'; } get parentTitle(): string { return this._title; } constructor() { } ngOnInit(): void { } runParentFunc() { this.parentGetMsg(); } } <p>父组件的 title 属性值:{{parentTitle}}</p> <p> <button (click)="runParentFunc()">调用父组件的方法</button> </p>对于使用 @Input 装饰器获取到的父组件数据,可以通过输入属性中的 setter 方法中进行重新赋值