关于Angular上手学习,可以去官网把示例先敲一遍,边做边学习。
点我传送门
下面将介绍一些关于Angular的基本知识。
生命周期
当你的应用通过调用构造函数来实例化一个组件或指令时,Angular 就会调用那个在该实例生命周期的适当位置实现了的那些钩子方法。
钩子方法 | 说明 |
---|---|
ngOnChanges() | 如果组件绑定过输入属性,那么在 ngOnInit() 之前以及所绑定的一个或多个输入属性的值发生变化时都会调用。 ( 注意:如果操作频繁,会严重影响性能。) |
ngOnInit() | 在 Angular 第一次显示数据绑定和设置指令/组件的输入属性之后,初始化指令/组件。只调用一次。 |
ngDoCheck() | 检测,并在发生 Angular 无法或不愿意自己检测的变化时作出反应。 |
ngAfterContentInit() | 当 Angular 把外部内容投影进组件视图或指令所在的视图之后调用。第一次 ngDoCheck() 之后调用,只调用一次。 |
ngAfterContentChecked() | 每当 Angular 检查完被投影到组件或指令中的内容之后调用。(ngAfterContentInit() 和每次 ngDoCheck() 之后调用) |
ngAfterViewInit() | 当 Angular 初始化完组件视图及其子视图或包含该指令的视图之后调用。第一次 ngAfterContentChecked() 之后调用,只调用一次。 |
ngAfterViewChecked() | 每当 Angular 做完组件视图和子视图或包含该指令的视图的变更检测之后调用。(ngAfterViewInit() 和每次 ngAfterContentChecked() 之后调用。) |
ngOnDestroy() | 在 Angular 销毁指令或组件之前立即调用。 |
组件获取初始数据在ngOnInit()进行。
下面图展示的是当用户单击 Create… 按钮,然后单击 Destroy… 按钮后的生命周期执行顺序和频率。
日志信息的日志和所规定的钩子调用顺序是一致的:先执行constructor构造函数,再 OnChanges、OnInit、DoCheck (3x)、AfterContentInit、AfterContentChecked (3x)、 AfterViewInit、AfterViewChecked (3x)和 OnDestroy
常用语法
*ngFor
结构型指令,通常用于遍历数组。
<div *ngFor="let product of products">
<h3>
{{ product.name }}
</h3>
</div>
*ngIf
用于条件判断。
<div *ngFor="let product of products">
<p *ngIf="product.description">
Description: {{ product.description }}
</p>
</div>
[ ]
用于属性绑定。
<div *ngFor="let product of products">
<h3>
<a [title]="product.name + ' details'">
{{ product.name }}
</a>
</h3>
</div>
( )
用于事件绑定。
<button (click)="share()">
Share
</button>
[( )]
用于双向数据绑定。
<textarea rows="2" [(ngModel)]="applyInfo.reason" placeholder="申请原因"></ion-textarea>
组件创建
第一步:执行命令
ng generate component child
执行完毕后,会生成四个文件。
分别为scss、html、.spec.ts(单元测试文件)、.ts 文件。
设定:父组件为HomePage,子组件为ChildComponent
ChildComponent组件内容
<div style="background: yellowgreen;width: 100%;height: 200px">
<h1>子组件区域</h1>
</div>
第二步:新建component.module.ts文件,引入和导出ChildComponent组件。
第三步:在home.module.ts中引入ComponentModule
第四步:使用ChildComponent组件
在父组件HomePage中,使用ChildComponent
<div style="background: pink;width: 100%;height: 100%;">
<h1>父组件区域</h1>
<app-child></app-child>
</div>
注意:子组建名字不要写错了,要取子组建@Component修饰器中的selector名。
第五步:刷新页面,子组建引入成功。
另外,我之前按照另外一种方式,直接在app.module.ts中引入ChildComponent,如下所示:
结果页面报错:
core.mjs:14621 NG0304: 'app-child' is not a known element:
1. If 'app-child' is an Angular component, then verify that it is part of this module.
2. If 'app-child' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
我想会不会是版本问题导致引入方式改变,官网上还有网上都是这种引入方式。
我现在demo使用的版本是angular13,用我上面步骤说的module.ts的引入方式就不会报错。
其他版本我还未尝试。
父子组件通信
1. 父组件向子组件传值
子组件或指令中的 @Input() 装饰器表示该属性可以从其父组件中获取值。
要使用 @Input(),就必须对父组件和子组件进行配置。
1)对子组件进行配置:
要使用 @Input() 装饰器,首先要导入 Input,然后用 @Input() 装饰该属性。
src/app/child/child.component.ts
import { Component, OnInit, Input } from '@angular/core';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.scss'],
})
export class ChildComponent implements OnInit {
@Input() contentText=''
constructor() { }
ngOnInit() {}
}
@Input() 属性可以是任意类型,比如 number、string、boolean 或 object。item 的值来自父组件。
接下来,在子组件模板中添加以下内容。
src/app/child/child.component.html
<div style="background: yellowgreen;width: 100%;height: 200px">
<h1>子组件区域</h1>
<h2>{{contentText}}</h2>
</div>
2)配置父组件
使用属性绑定把子组件的 contentText 属性绑定到父组件的 contentText 属性上。
在父组件类中,为 contentText 指定一个值:
src/app/home/home.page.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
contentText='台湾回归'
constructor() {}
}
src/app/home/home.page.html
<div style="background: pink;width: 100%;height: 100%;">
<h1>父组件区域</h1>
<app-child [contentText]='contentText'></app-child>
</div>
通过 @Input(),Angular 把 contentText 的值传给子组件。
方括号 [] 中的目标就是子组件中用 @Input() 装饰的那个属性。绑定源(等号的右边部分)则是父组件传给内嵌组件的数据。
要想监视 @Input() 属性的变化,可以用 Angular 的生命周期钩子OnChanges 。
2. 子组件向父组件传值
子组件或指令中的 @Output() 装饰器允许数据从子组件传给父组件。
功能需求:点击子组件的按钮,更新父组件的‘祝福语’。
1)配置子组件
在子组件类中导入 Output 和 EventEmitter,并添加clickMe方法。
src/app/child/child.component.html
<div style="background: yellowgreen;width: 100%;height: 200px">
<h1>子组件区域</h1>
<h2>{{contentText}}</h2>
<button style="width: 150px;height:30px;background: #fff;" (click)="clickMe('祝祖国繁荣昌盛!')">点我祝福</button>
</div>
src/app/child/child.component.ts
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.scss'],
})
export class ChildComponent implements OnInit {
@Input() contentText=''
@Output() notify= new EventEmitter<string>()
constructor() { }
ngOnInit() {}
clickMe(value:string){
this.notify.emit(value)
}
}
说明:
@Output() - 一个装饰器函数,它把该属性标记为数据从子组件进入父组件的一种途径
newItemEvent - 这个 @Output() 的名字
EventEmitter - 这个 @Output() 的类型
new EventEmitter() - 使用 Angular 来创建一个新的事件发射器,它发出的数据是 string 类型的。
2)配置父组件
src/app/home/home.page.html
<div style="background: pink;width: 100%;height: 100%;">
<h1>父组件区域</h1>
<app-child [contentText]='contentText' (notify)="notifyMe($event)"></app-child>
<p>祝福语:{{describe}}</p>
<p></p>
</div>
src/app/home/home.page.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
contentText='台湾回归'
describe=''
constructor() {}
notifyMe(value){
this.describe=value
}
}