搜索
首页web前端js教程Angular知识点分享:聊聊表单、管道、绑定、指令、通信和周期

本篇文章给大家分享Angular的一些知识点,介绍一下Angular的两表单(模板驱动表单和响应式表单)、三管道(内置管道、链式管道、自定义管道)、三绑定、三指令、五通信、八周期,希望对大家有所帮助!

Angular知识点分享:聊聊表单、管道、绑定、指令、通信和周期

1 Angular的两大表单

1.1 模板驱动表单

? 模板驱动表单:引入FormsModule模块,表单的控制逻辑都是写在模板里的,每一个表单元素都是和一个负责管理内部表单模型的指令关联起来的。【相关教程推荐:《angular教程》】

import { Component, OnInit } from '@angular/core';
import { NgForm } from '@angular/forms';

@Component({
  selector: 'app-module-form',
  template:`
  <form #moduleForm="ngForm" (submit)="OnSubmit(moduleForm)">
    <label>用户名:
      <input type="text" name="username" ngModel required minlength="2" maxlength="6" #username="ngModel"><br>
      <ng-container *ngIf="username.touched&&username.errors">
        <div *ngIf="username.errors.required">请输入用户名</div>
        <div *ngIf="username.errors.minlength">最少2个字符</div>
        <div *ngIf="username.errors.maxlength">最多6个字符</div>
      </ng-container>
    </label>

    <label>
      密  码:
      <input style="margin-top: 10px;" type="text" name="password" ngModel required minlength="6" pattern="[a-zA-Z0-9]+" #password="ngModel"><br>
      <ng-container *ngIf="password.touched&&password.errors">
        <div *ngIf="password.errors.required">请输入密码</div>
        <div *ngIf="password.errors.minlength">最少6个字符</div>
        <div *ngIf="password.errors.pattern">至少包含大小写、数字</div>
      </ng-container>
    </label>

    <button style="margin-top: 20px;" type="submit" [disabled]="!moduleForm.valid">提交</button>
  </form>
  `,
  styleUrls: [&#39;./module-form.component.less&#39;]
})
export class ModuleFormComponent implements OnInit {
  constructor() { }
  ngOnInit() {
  }
  OnSubmit(moduleForm:NgForm){
    console.log(moduleForm.value);
  }
}

1.2 响应式表单

? 响应式表单:需要引入ReactiveFormsModule模块,在响应式表单中,视图中的每个表单元素都直接链接到一个表单模型。

  • FormControl:是构成表单的基本单位。实例用于追踪单个表单控件的值和验证状态
  • FormGroup:用于追踪一个表单控件组的值和状态。
  • FormGroup和FormArray的区别:formgroup既可以代表表单一部分也可以代表整个表单;formarray有一个额外的长度属性,它的formControl是没有相关的key的,只能通过访问formarray中的元素。
<input [formControl]="username">
<!--不带表单的input-->
//原始的定义方法
export class ReactiveRegistComponent implements OnInit {
  formModel:FormGroup;
  constructor() {
    this.formModel=new FormGroup({
      username:new FormControl(),
      mobile:new FormControl(),
      passwordsGroup: new FormGroup({
        password:new FormControl(),
        pconfirm:new FormControl(),
      })
    });
  }
}

//使用formBuilder后的定义
constructor(fb:FormBuilder) {
  this.formModel=fb.group({
    username:[&#39;&#39;],
    mobile:[&#39;&#39;],
    passwordsGroup: fb.group({
      password:[&#39;&#39;],
      pconfirm:[&#39;&#39;],
    })
  });
}
import { Component, OnInit } from &#39;@angular/core&#39;;
import { FormBuilder, FormGroup, NgForm, Validators } from &#39;@angular/forms&#39;;

@Component({
  selector: &#39;app-module-form&#39;,
  // templateUrl: &#39;./module-form.component.html&#39;,
  template:`
    <form [formGroup]="form">
    <label>用户名:
      <input type="text"  formControlName="username"><br>
      <ng-container *ngIf="form.controls[&#39;username&#39;].errors?.[&#39;required&#39;]"><div style="color: red;">请输入用户名</div></ng-container>
      <ng-container *ngIf="form.controls[&#39;username&#39;].errors?.[&#39;maxlength&#39;]"><div style="color: red;">最多只能有6个字符</div></ng-container>
    </label>

    <label>
      密  码:
      <input style="margin-top: 10px;"  formControlName="password"><br>
      <ng-container *ngIf="form.controls[&#39;password&#39;].errors?.[&#39;required&#39;]"><div style="color: red;">请输入密码</div></ng-container>
    </label>
  </form>
  `,
  styleUrls: [&#39;./module-form.component.less&#39;]
})
export class ModuleFormComponent implements OnInit {
  form!: FormGroup;
  constructor(private fb: FormBuilder) { }

  ngOnInit() {
    this.form = this.fb.group({
      username:[null,[Validators.required,Validators.maxLength(6)]],
      password:[null,[Validators.required]],
    })
  }
}
  • 自定义验证器:
export function whiteSpaceValidator(): ValidatorFn {
  // 不能全输入空格,验证
  return (control: FormControl): { [s: string]: boolean } => {
    const reg = new RegExp(/\s/g);
    if (reg.test(control.value)) {
      return { required: true };
    }
  };
}

2 Angular管道

  • 管道:把数据作为输入,然后转换它并给出输出。

2.1 内置管道

? Angular的一些内置管道:如date、uppercase、lowercase、currency、percent等,不用引入,直接在任何组件中使用。注意:用date转化的数据不能为字符串,必须为Date类数据

<!-- curDate = new Date(); -->
<!-- 当前时间日期为Apr 20, 2022 -->
<p>当前时间日期为{{curDate|date}}</p>

<!-- 管道参数化:当前时间日期为2022/04/20 -->
<p>当前时间日期为{{curDate|date:"yyyy/MM/dd"}}</p>

<!-- title = "Hello World!"; -->
<!-- 转大写HELLO WORLD! -->
<p>转大写{{title|uppercase}}</p>
<!-- 转小写hello world! -->
<p>转小写{{title|lowercase}}</p>

<!-- 转换金额字符串$0.26 -->
<p>转换金额字符串{{0.259|currency}}</p>

<!-- 转换金额百分比26% -->
<p>转换金额百分比{{0.259|percent}}</p>

2.2 链式管道

? 链式管道:管道以多个条件指定格式输出。

<!-- 当前时间日期为wednesday, april 20, 2022 -->
<p>当前时间日期为{{curDate|date:&#39;fullDate&#39;|lowercase}}</p>

2.3 自定义管道

? 自定义管道:在app.module文件的declarations中进行声明就可以在任何一个组件中使用了。

<!-- 600000毫秒真实时间:00天00时10分00秒 -->
<p>600000毫秒真实时间:{{600000|TimeFormater}}</p>
import { PipeTransform, Pipe } from &#39;@angular/core&#39;;

@Pipe({
  name: &#39;TimeFormater&#39;,
})
export class TimeFormaterPipe implements PipeTransform {
// // 传入的是一个一毫秒为单位的时间数
  transform(value) {
    if (!value || value <= 0) {
      return &#39;00天00时00分00秒&#39;;
    }
    const time = Math.abs(value);
    const transecond = Math.round(time / 1000); // 转化为秒
    const day = Math.floor(transecond / 3600 / 24); // 获取天数
    const hour = Math.floor((transecond / 3600) % 24); // 获取小时,取余代表不满一天那部分
    const minute = Math.floor((transecond / 60) % 60); // 获取分,取余代表不满小时那部分
    const second = transecond % 60;
    return `${this.formatTime(day)}天${this.formatTime(hour)}时${this.formatTime(minute)}分${this.formatTime(second)}秒`;
  }

  formatTime(t) {
    return t < 10 ? &#39;0&#39; + t : &#39;&#39; + t;
  }
}

3 Angular的三大绑定

3.1属性绑定

? 属性绑定的属性指的是元素、组件、指令的属性。属性的绑定是单向绑定,从组件的属性流动到目标元素的属性。

<!--属性绑定图片路径,动态获取-->
<img [src]="imgUrl">

3.2 attribute、class和style绑定

?attribute绑定:并非所有属性都有可供属性绑定。是HTML标签上的特性,它的值只能够是字符串。通过attr.特性名绑定。而比如标签中的id、src等这些属于Property(属性,DOM中的属性,是JavaScript里的对象),这些可以直接绑定就可。而attribute绑定如下:

<table [border]="1">
  <tr><td id="attr" [attr.colspan]="1+1">One-Two</td></tr>
  <tr><td>Five</td><td>Six</td></tr>
</table>

?class的绑定:静态绑定、单一属性动态绑定方式、多属性动态绑定方式、ngCLass指令绑定。

  .test1{
    width: 100px;
    height: 100px;
    border: 1px solid;
  }

  .test2{
    width: 100px;
    height: 100px;
    background-color: yellowgreen;
  }

(1)静态绑定:可以是一个,也可以是多个,多个的class就会融合起来。

<div class="test1"></div>
<div class="test1 test2"></div>
<!--多个样式会重叠-->
<div [class]="&#39;test1&#39;"></div>
<div [class]="&#39;test1 test2&#39;"></div>

(2)单一属性动态绑定方式:取在css文件中定义好的样式进行绑定,class.样式的class名

<div [class.test1]="true"></div>
<div [class.test2]="true"></div>

(3)多属性动态绑定方式:class的绑定

<div [class]="moreClass"></div>
<div [ngClass]="moreClass"></div>
moreClass:object = {
    &#39;test1&#39;:true,
    &#39;test2&#39;:true
}

?style的绑定:单一样式绑定、带单位的单一样式绑定、多个样式绑定。 (1)单一样式的绑定

<div [style.width]="&#39;200px&#39;"></div>

(2)带单位的单一样式绑定

<div [style.width.px]="&#39;200&#39;"></div>

(3)多个样式绑定

`<div [style]="moreStyle">绑定多个形式的style</p>`
moreStyle:string =  &#39;width: 100px;height: 200px&#39;;

3.3 事件绑定

?事件绑定:带()的特性就是事件绑定。括号内代表的是目标事件。而下面例子的事件绑定就是点击事件的绑定。

<button (click)="save()"></button>

(1)目标事件是原生DOM元素事件,input是DOM元素input的原生事件。

//html
<input [value]="currentUser.name" (input)="getValue($event)">

//js
currentUser={
    &#39;name&#39;:&#39;&#39;
}
getValue(ev:any){
    this.currentUser.name = ev.target.value;
    console.log(this.currentUser.name);
}

(2)目标事件是指令:比如ngClickngDblclick等。

(3)目标事件是自定义事件。目标事件 (子组件的EventEmitter实例变量)="父组件的方法(子组件数据)" 下文的父子组件通信已经有详解?。

4 Angular的三大指令

4.1 属性型指令

? 属性型指令:该指令可改变元素、组件或其他指令的外观和行为。比如:

  • ngClass指令:可以通过动态地添加或移除css类来控制css来如何显示。
  • ngStyle指令:可以同时设置多个内联样式。
  • ngModel指令:可以双向绑定到HTML表单中的元素。
  • 创建属性型指令:在app.module文件中的declarations数组中进行声明就可以在任何组件的标签元素中调用,如下:
<p appHighlight>看一下指令</p>
// Directive:在declarations
import { Directive, ElementRef } from &#39;@angular/core&#39;;

@Directive({
  selector: &#39;[appHighlight]&#39;
})
export class HighlightDirective {

  constructor(el:ElementRef) {
    el.nativeElement.style.backgroundColor = &#39;yellow&#39;;
  }
}
import { Directive, ElementRef, HostListener } from &#39;@angular/core&#39;;

@Directive({
  selector: &#39;[appHighlight]&#39;
})
export class HighlightDirective {
  constructor(private el:ElementRef) {
  }
  
  // 监听鼠标悬浮背景颜色设置
  @HostListener(&#39;mouseenter&#39;) onMouseEnter(){
    this.hightlight(&#39;yellow&#39;);
  }
  // 监听鼠标离开背景颜色设置
  @HostListener(&#39;mouseleave&#39;) onMouseLeave(){
    this.hightlight(&#39;&#39;);
  }

  private hightlight(color:string){
    this.el.nativeElement.style.backgroundColor = color;
  }
}

4.2 结构型指令

? 结构型指令:该指令通过添加或移除DOM元素来改变DOM布局。每一个宿主元素都只能有一个结构型指令。比如ngif和ngfor不能在同一元素出现。如ngif、ngfor、ngSwitch(本身是属性型指令,它控制了两个结构型指令ngSwitchCase和ngSwitchDefault),结构型指令一般都是带***符号的**。

  • 自定义结构型指令:
import { Directive, Input, TemplateRef, ViewContainerRef } from &#39;@angular/core&#39;;

@Directive({
  selector: &#39;[appTagdisplay]&#39;
})
export class TagdisplayDirective {
  private hasView = false;
  // ViewContainerRef访问视图容器
  constructor(private templateRef:TemplateRef<any>,private viewContainer:ViewContainerRef) { }

  @Input() set appTagdisplay(condition:boolean){
    if(!condition&&!this.hasView){
      // 视图容器创建一个内嵌的视图
      this.viewContainer.createEmbeddedView(this.templateRef);
      this.hasView = true;
    }else if(condition&&this.hasView){
      // 清除该容器,销毁该视图
      this.viewContainer.clear();
      this.hasView = false;
    }
  }
}
<div>
  <h1>自定义结构指令</h1>
  <p *appTagdisplay="false">
    该段显示,因为appTagdisplay为false
  </p>
  <p *appTagdisplay="true">
    该段不显示,因为appTagdisplay为true
  </p>
</div>

4.3 组件

? 组件:也是一种指令,该指令拥有模板。

5 Angular的五大组件通信

5.1 Input与Output实现父子组件通信

通过下面的例子我们会发现Input和Output的操作都在子组件中。父传子:在父组件中动态绑定属性,在子组件中Input获取父组件传来的属性。子传父:子组件创建一个实例化EventEmitter对象,EventEmitter 的核心就是事件触发与事件监听器功能的封装;父组件:通过事件绑定调用带参自定义函数接受子组件传来的数据(自定义函数的参数)。

? 父组件:双向绑定fatherData也就是当前输入框输入的信息,点击发送事件触发传给子组件的currentData添加数据并清空当前输入框的信息。

<div class="chan">
  <div class="father">
    <ng-container *ngIf="!isClear">
      <div *ngFor="let item of currentData">
      <span>{{item}}</span>
    </div>
    </ng-container>
    <div class="footer">
      <input style="width:178px" [(ngModel)]="fatherData"/>
      <button (click)="send()">发送</button>
      <button (click)="isClear=true">清空记录</button>
    </div>
  </div>
  <app-son [dataSource]="currentData" (sonSend)="getSonInfo($event)"></app-son>
</div>
import { Component, OnInit } from &#39;@angular/core&#39;;

export class FatherComponent implements OnInit {
  isClear:boolean=false;
  fatherData:any;
  currentData:Array<any>=[];
  constructor() { }

  ngOnInit() {
    this.fatherData = this.currentData;
  }

  send(){
    this.currentData.push("我是父组件的数据:"+this.fatherData);
    this.fatherData=&#39;&#39;;
  }

  getSonInfo(event:any){
    this.currentData.push("我是子组件的数据:"+event);
  }
}

? 子组件:输入框输入sonData,点击发送事件触发子组件事件发射数据,然后父组件就可以通过子组件绑定的事件发射从父组件通过事件方法获取当前子组件发送的数据。

<div class="son">
  <ng-container *ngIf="!isClear">
    <div *ngFor="let item of currentData">
    <span>{{item}}</span>
    </div>
  </ng-container>
  <div class="footer">
    <input  style="width:178px" [(ngModel)]="sonData"/>
    <button (click)="send()">发送</button>
    <button (click)="isClear=true">清空记录</button>
  </div>
</div>
import {  OnInit } from &#39;@angular/core&#39;;

export class SonComponent implements OnInit{
  @Input() dataSource:any=0;
  @Output() sonSend = new EventEmitter<any>();
  isClear:boolean=false;
  sonData:any;
  currentData:Array<any>=[];
  constructor() { }

  ngOnInit(): void {
    this.currentData = this.dataSource;
  }

  send(){
    this.sonSend.emit(this.sonData);
    // this.currentData.push("我是子组件的数据:"+this.sonData);
    this.sonData=&#39;&#39;;
  }
}

1.png

5.2 通过本地变量实现父子组件的通信

在父组件的模板中创建一个代表子组件的本地变量,通过调用这个变量就可以调用子组件中的属性和方法。

<div>我是父组件</div>
<div>子组件:{{sonTpl.myName}}</div>
<app-son #sonTpl></app-son>

5.3 通过@ViewChild实现父子组件的通信

父组件的js中定义@ViewChild(SonComponent) childTpl: any;,注意在html必须要调用子组件元素,不然会直接报错,且不能直接调用childTpl.myName获取子组件中的变量。

<div>我是父组件</div>
<button (click)="childTpl.getName()">子组件按钮</button>
<app-son></app-son>
// 子组件中的getName
 getName(){
    console.log(&#39;我是子组件的getName方法&#39;);
 }

5.4 通过共享服务Service实现非父子组件通信

栗子来自书籍《Angular企业级应用开发实战》-p143:

2.png

? Service服务:主要控制准备开始、和确认按钮的动作进行消息的传递。注意这个服务的定义一定是共享的,不要在各个组件下独自注入providers中,因为单独引入service只是在当前组件有效,每个组件调用一次都是独立的,互不影响,这就不是组件通信需要的。

import { Injectable } from &#39;@angular/core&#39;;
import { Subject } from &#39;rxjs&#39;;

@Injectable({
  providedIn: &#39;root&#39;
})
export class MissionService {
  // 源
  private missionAnnounceSource = new Subject<string>();
  private misssionConfirmedSource = new Subject<string>();

  // 流
  // asObservable:可观察的序列,隐藏源序列的身份。
  missionAnnounce$ = this.missionAnnounceSource.asObservable();
  missionConfirm$ = this.misssionConfirmedSource.asObservable();
  constructor() {}

  announceMission(mission:string){
    this.missionAnnounceSource.next(mission);
  }

  confirmMission(astronaut:string){
    this.misssionConfirmedSource.next(astronaut);
  }
}

? MissioncontrolComponent:这是一个主要界面的组件,在界面中调用了astronaut组件。当前组件就是父组件,而astronaut组件就是一个子组件。

import { Component, OnInit } from &#39;@angular/core&#39;;
import { MissionService } from &#39;src/app/service/mission.service&#39;;

@Component({
  selector: &#39;app-missioncontrol&#39;,
  template: `<h2>导弹控制器</h2>
  <button (click)="announce()">准备开始</button>
  <app-astronaut *ngFor="let item of astronauts" [astronaut]="item">
  </app-astronaut>
  <h3>日志</h3>
  <ul>
    <li *ngFor="let event of history">{{event}}</li>
  </ul>
  `,
})
export class MissioncontrolComponent implements OnInit {
  astronauts = [&#39;操作员1&#39;,&#39;操作员2&#39;,&#39;操作员3&#39;];
  history:string[] = [];
  missions = [&#39;发射导弹&#39;];
  nextMession = 0;
  constructor(private misssionSvc:MissionService) {
     // 获取子组件保存的信息,获取是哪一个操作员点击确认了
     misssionSvc.missionConfirm$.subscribe((astronaut)=>{
       this.history.push(`${astronaut}已经确认`);
     })
  }

  announce(){
    let mission = this.missions[this.nextMession++];
    this.misssionSvc.announceMission(mission);
    this.history.push(`任务"${mission}"进入准备`);
    if(this.nextMession>=this.missions.length){
      this.nextMession = 0;
    }
  }
  ngOnInit(): void {
  }
}

? AstronautComponent:点击确认,向父组件传递确认的操作员信息。

import { Component, Input, OnInit, OnDestroy } from &#39;@angular/core&#39;;
import { Subscription } from &#39;rxjs&#39;;
import { MissionService } from &#39;src/app/service/mission.service&#39;;

@Component({
  selector: &#39;app-astronaut&#39;,
  template: `
  <p>
  {{astronaut}}:<strong>{{mission}}</strong><button (click)="confirm()" [disabled]="!announced||confirmed">确认</button>
  </p>
  `,
})
export class AstronautComponent implements OnInit,OnDestroy{
  @Input() astronaut:string=&#39;&#39;;
  mission = &#39;<没有任务>&#39;;
  confirmed = false;
  announced = false;
  subscription:Subscription;
  constructor(private missionSvc:MissionService) {
    // 获取父组件的数据
    this.subscription = missionSvc.missionAnnounce$.subscribe((mission)=>{
      this.mission = mission;// 发射导弹
      this.announced = true;// 激活确认按钮
      this.confirmed = false;
    })
  }
  confirm(){
    // 禁用按钮
    this.confirmed = true;
    // 点击确认,保存当前的操作员数据
    this.missionSvc.confirmMission(this.astronaut);
  }
  ngOnDestroy(): void {
    // 防止内存泄漏
    this.subscription.unsubscribe();
  }
  ngOnInit() {
  }
}

5.5 路由传值

? 按钮点击跳转:路由传参数由分号隔开。

import { Component, OnInit } from &#39;@angular/core&#39;;
import { Router } from &#39;@angular/router&#39;;

@Component({
  selector: &#39;app-father&#39;,
  template:`<button (click)="linkSon()">按钮跳到儿子组件中</button>`
})
export class FatherComponent implements OnInit {
  obj:any=[
    &#39;书悟空&#39;,
    &#39;唐僧&#39;,
  ];
  constructor(private router:Router) {}

  ngOnInit() {}

  linkSon(){
    this.router.navigate([&#39;/son&#39;,{ name:this.obj,id:10010}]);
    //http://localhost:4209/son;name=书悟空,唐僧;id=10010
  }
}
// private route:ActivatedRoute
this.route.params.subscribe((route)=>{
       console.log(route);
})

? 链接点击跳转:路由传参通过queryParams属性控制,由?、&符号分隔开。

<a [routerLink]="[&#39;/son&#39;]" [queryParams]="{id:10010,name:this.obj}">链接跳到儿子组件中</a>
// http://localhost:4209/son?id=10010&name=书悟空&name=唐僧
// private route:ActivatedRoute
this.route.queryParams.subscribe((route)=>{
       console.log(route);
})

? 链接点击跳转:直接是用/分割路由传参。

{ path: &#39;son/:id&#39;, component: SonComponent },
<a [routerLink]="[&#39;/son&#39;,10010]">链接跳到儿子组件中</a>
// http://localhost:4209/son/10010
// private route:ActivatedRoute
this.route.params.subscribe((route)=>{
       console.log(route);
})

还有其他通信方式:浏览器本地传值(localStorge、SessionStorge)、cookie

6 Angular的八大生命周期

6.1 ngOnChanges()

当angular检测到组件(或指令)重新设置数据绑定输入属性时响应。在被绑定的输入属性的值发生变化时调用,首次调用一定会发生在ngOnInit()之前,每一次改变绑定数据就调用一次这个钩子。OnChanges() 对应的函数 ngOnChanges(),该函数获取了一个对象,对象把每个发生变化的属性名映射在SimpleChange对象中,对象有属性当前值currentValue前一个值previousValue

? 父组件

<!--父组件html-->
<div>
  <span>我是父组件:</span>
  <input  [(ngModel)]="dataSource"/>
  <span style="margin-left: 20px;">{{dataSource}}</span>
</div>
<div style="height: 20px;"></div>
<app-two [data]="dataSource"></app-two>

? 子组件

<!--子组件TwoComponent html-->
<div>
  <span>我是子组件:</span>
  <button (click)="increment()">+</button>
  <span style="margin: 0 20px;">{{data}}</span>
  <button (click)="decrement()">-</button>
</div>
import { Component, Input, OnInit, SimpleChanges, OnChanges } from &#39;@angular/core&#39;;
// 子组件js
export class TwoComponent implements OnInit,OnChanges {
  @Input() data:any=0;
  constructor() { }
  ngOnInit(): void {
    console.log(&#39;ngOnInit&#39;,this.data);
  }

  increment(){
    this.data++;
  }
  decrement(){
    this.data--;
  }

  ngOnChanges(changes: SimpleChanges): void {
    console.log("previousValue:",changes[&#39;data&#39;].previousValue);
    console.log("currentValue:",changes[&#39;data&#39;].currentValue);
  }
}

注意地,在子组件中操作是不能触发Onchanges钩子函数地,它是控制组件上属性的改变而触发

3.png

4.png

6.2 ngOnInit()

在Angular第一次显示数据绑定和设置指令/组件的输入属性之后,初始化指令/组件,在第一轮ngOnChanges()完成之后调用,只调用一次

6.3 ngDoCheck()

检测变化,在每一个Angular变更检测周期(变化监测)中调用,在执行ngOnChangesngOnInit()方法之后调用。不管是数据绑定还是鼠标的点击事件,只要触发了都会触发这个钩子的调用。

<div>
  <input  [(ngModel)]="dataSource"/>
  <span style="margin-left: 20px;">{{dataSource}}</span>
</div>
import { DoCheck,OnInit } from &#39;@angular/core&#39;;

export class SonComponent implements OnInit,DoCheck {
  dataSource:any;
  constructor() { }

  ngOnInit(): void {
    console.log("ngOnInit!");
  }

  ngDoCheck(): void {
    console.log("DoCheck:",this.dataSource);
  }
}

5.png

6.4 ngAfterContentInit()

把内容投影进组件之后调用,在第一次执行ngDoCheck方法之后调用,只调用一次

import { AfterContentChecked, AfterContentInit,DoCheck, Input, OnInit } from &#39;@angular/core&#39;;

export class SonComponent implements OnInit,DoCheck,AfterContentInit{
  @Input() data:any=0;
  dataSource:any;
  constructor() { }

  ngOnInit(): void {
    console.log("ngOnInit!");
  }

  ngAfterContentInit(): void {
    console.log("ngAfterContentInit!",this.dataSource);
  }

  ngDoCheck(): void {
    console.log("DoCheck:",this.dataSource);
  }
}

6.png

6.5 ngAfterContentChecked()

在每次完成被投影组件内容的变更检测之后调用。在执行ngAfterContentInit()ngDoCheck()方法之后调用。

import { AfterContentChecked, AfterContentInit, DoCheck, Input,  OnInit } from &#39;@angular/core&#39;;

export class SonComponent implements OnInit,DoCheck,AfterContentInit,AfterContentChecked{
  @Input() data:any=0;
  dataSource:any;
  constructor() { }

  ngOnInit(): void {
    console.log("ngOnInit!");
  }

  ngAfterContentInit(): void {
    console.log("ngAfterContentInit!",this.dataSource);
  }

  ngAfterContentChecked(): void {
    console.log("ngAfterContentChecked!",this.dataSource);
  }

  ngDoCheck(): void {
    console.log("DoCheck:",this.dataSource);
  }
}

7.png

6.6 ngAfterViewInit()

在初始化完组件视图及其子视图之后调用,在第一次执行ngAfterContentChecked()方法之后调用,只调用一次

export class SonComponent implements OnInit,DoCheck,AfterContentInit,AfterContentChecked,AfterViewInit{
  dataSource:any;
  constructor() { }

  ngOnInit(): void {
    console.log("ngOnInit!");
  }

  ngAfterContentInit(): void {
    console.log("ngAfterContentInit!",this.dataSource);
  }

  ngAfterContentChecked(): void {
    console.log("ngAfterContentChecked!",this.dataSource);
  }

  ngAfterViewInit(): void {
    console.log("ngAfterViewInit!");
  }

  ngDoCheck(): void {
    console.log("DoCheck:",this.dataSource);
  }
}

8.png

6.7 ngAfterViewChecked()

在每次完成组件视图和子视图的变更检测之后调用。在执行ngAfterViewInit()ngAfterContentChecked()方法之后调用。

9.png

6.8 ngOnDestroy()

在Angular每次销毁指令/组件之前调用并清扫,在这里反订阅可观察对象和分离事件处理器,以防内存泄漏。什么时候会调用这个生命周期呢?也就是平时我们切换组件或从一个组件跳转到另一个组件的时候,这时候就会触发组件的销毁。

更多编程相关知识,请访问:编程视频!!

以上是Angular知识点分享:聊聊表单、管道、绑定、指令、通信和周期的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
超越浏览器:现实世界中的JavaScript超越浏览器:现实世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在现实世界中的应用包括服务器端编程、移动应用开发和物联网控制:1.通过Node.js实现服务器端编程,适用于高并发请求处理。2.通过ReactNative进行移动应用开发,支持跨平台部署。3.通过Johnny-Five库用于物联网设备控制,适用于硬件交互。

使用Next.js(后端集成)构建多租户SaaS应用程序使用Next.js(后端集成)构建多租户SaaS应用程序Apr 11, 2025 am 08:23 AM

我使用您的日常技术工具构建了功能性的多租户SaaS应用程序(一个Edtech应用程序),您可以做同样的事情。 首先,什么是多租户SaaS应用程序? 多租户SaaS应用程序可让您从唱歌中为多个客户提供服务

如何使用Next.js(前端集成)构建多租户SaaS应用程序如何使用Next.js(前端集成)构建多租户SaaS应用程序Apr 11, 2025 am 08:22 AM

本文展示了与许可证确保的后端的前端集成,并使用Next.js构建功能性Edtech SaaS应用程序。 前端获取用户权限以控制UI的可见性并确保API要求遵守角色库

JavaScript:探索网络语言的多功能性JavaScript:探索网络语言的多功能性Apr 11, 2025 am 12:01 AM

JavaScript是现代Web开发的核心语言,因其多样性和灵活性而广泛应用。1)前端开发:通过DOM操作和现代框架(如React、Vue.js、Angular)构建动态网页和单页面应用。2)服务器端开发:Node.js利用非阻塞I/O模型处理高并发和实时应用。3)移动和桌面应用开发:通过ReactNative和Electron实现跨平台开发,提高开发效率。

JavaScript的演变:当前的趋势和未来前景JavaScript的演变:当前的趋势和未来前景Apr 10, 2025 am 09:33 AM

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

神秘的JavaScript:它的作用以及为什么重要神秘的JavaScript:它的作用以及为什么重要Apr 09, 2025 am 12:07 AM

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

Python还是JavaScript更好?Python还是JavaScript更好?Apr 06, 2025 am 12:14 AM

Python更适合数据科学和机器学习,JavaScript更适合前端和全栈开发。 1.Python以简洁语法和丰富库生态着称,适用于数据分析和Web开发。 2.JavaScript是前端开发核心,Node.js支持服务器端编程,适用于全栈开发。

如何安装JavaScript?如何安装JavaScript?Apr 05, 2025 am 12:16 AM

JavaScript不需要安装,因为它已内置于现代浏览器中。你只需文本编辑器和浏览器即可开始使用。1)在浏览器环境中,通过标签嵌入HTML文件中运行。2)在Node.js环境中,下载并安装Node.js后,通过命令行运行JavaScript文件。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
4 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能