Angular常用基础回顾

一.组件生命周期

组件函数被调用过程如下,其中constructor不属于生命周期函数,其他都是

在这里插入图片描述

1.组件生命周期函数
  • 实际上类上implement onXXX可以不加(即接口实现是可选的),只要类中有对应的ngXXX()方法就会识别成对应的钩子函数去执行【推荐添加:由于误删除某个钩子函数会进行提醒;对组件设计到哪些生命周期一目了然】
  • ngOnChanges(simpleChange:SimpleChange)在@Input属性发生变化的时候调用,参数SimpleChange类型对象是字典类型,所有的键都是所有输入@Input的属性名,所有的值还是字典对象,其中是当前值、是否第一次被改变、上一个值
  • ngOnInit()组件初始化完成时调用
  • ngDoCheck()在组件脏值检测的时候调用
  • ngAfterContentInit()当组件内容初始化完成的时候调用【组件内容的初始化】
  • ngAfterContentChecked()对组件里面的内容脏值检测之后进行的调用【组件内容的脏值检测】
  • ngAfterViewInit()在组件视图初始化完成后的调用(当前组件和子组件渲染完成时调用)【组件视图的初始化】
  • ngAfterViewChecked()组件视图的脏值检测之后进行的调用【组件视图的脏值检测】
  • ngOnDestory()组件销毁时调用【通常是父组件通过ngIf方式引用或路由发生变化的时候会销毁组件】。通常需要做一些清理工作,如在当前组件中使用了setTimeout()/setInterval()类似方法需要在组件销毁的时候清理掉,否则会导致内存溢出

二.组件类中引用模板

1.模板在组件类中的引用
  • 引用实例代码

    • html

      <div #helloDiv>
          ...
      </div>
      
    • ts类

      export class AppComponent {
          @ViewChild('helloDiv',{static:true}) //如果此模板是在ngIf包含之下的static为false;如果不是在ngIf包含之下的就是静态的即是true
          helloDivRef: ElementRef;
          
          ngAfterViewInit() {
              // 通过nativeElement属性的innerHTML添加内容
              this.helloDivRef.nativeElement.innerHTML = `<span>Hello</span>`;
          }
      }
      
  • html标签#后面是给模板或者DOM元素起一个引用名字,以便可以在组建类或模板中进行引用

  • ElementRef是DOM元素的一个包装类,因为DOM元素不是Angular中的类,所以需要一个包装类以便在Angular中使用和标识其类型。其中ElementRef中的nativeElement是指向DOM节点的

三.在模板中引用多个元素

1.模板在组件类中的引用
  • 通过指明类型引用模板中的组件

    • 模板中使用AppTestComponent组件,selector是app-test

      <app-test></app-test>
      
    • 组建类

      @ViewChild('AppTestComponent')
      appTest: AppTestComponent;
      
  • 如果想引用模板中的Angular组件,@ViewChild中可以使用引用名,也可以使用组件类型

2.引用多个模板元素
  • 通过@ViewChildren装饰器声明QueryList<ElementRef>类型的方式引用多个模板元素

    • 模板内容

      <img
           #img
           *ngFor="let item of items"
           [src]="item.imgUrl"
           [alt]="item.caption"
           />
      
    • 组建类

      @ViewChild('img')
      imgs: QueryList<ElmentRef>;
      
      // 通过nativeElement操作实现高度样式的变更
      ngAfterViewInit() {
          this.imgs.forEach(item => item.nativeElement.style.height='100px');//将高度变成100px
      }
      
  • 可以使用@ViewChildren,在@ViewChildren中使用引用名或者使用Angular组件/指令的类型。声明类型为QueryList<?>

  • 通常我们对@ViewChild/@ViewChildren声明的元素都放在ngAfterViewInit生命周期中操作,以免元素还没有加载被调用是空的

3.Render2的使用
  • 直接操作DOM在Angular中不推荐,推荐使用Renderer2[在@angular/core中导入]

    export class TestComponent {
    	constructor(private  renderer2: Renderer2) {}  
        
        ngAfterViewInit() {
            this.imgs.forEach(item=> {
                this.renderer2.setStyle(item.nativeElement, 'height', '100px');
                //等同于this.imgs.forEach(item => item.nativeElement.style.height='100px');
            });
        }
    }
    
  • 使用Renderer2更安全,因为直接操作DOM如果是用户添加进来的代码将不会检查的插入,而Renderer2会进行相关的检查

4.@ViewChild总结
  • @ViewChild用来在类中引用模板中的视图节点
  • 可以使Angular组件,也可以是HTML元素
  • 在AfterViewInit中可以安全的使用@ViewChild引用的元素
  • 推荐使用Renderer2操作DOM元素

四.组件的双向绑定

1.ngModel
  • 是FormsModule中提供的指令[需要引入FormsModule才能使用 ]
  • 使用[(ngModel)]="变量"形式进行双向绑定
  • 其实是一个语法糖,等同于[ngModel]="username" (ngModelChange)="username=$event"
2.自定义类似ngModel的语法糖
  • 定义组件属性_username和对外输出的变化事件

    export class TestComponent {
        private _username = '';
        @Output()
        usernameChange = new EventEmitter<>();
        @Input()
        public get username(): string {//get是属性的访问符
            return this._username;
        }
        
        public set username(value:string) {//写属性值
            this._username = value;
            this.usernameChange.emit(value);//在写入的同时把事件发射出去
        }
    }
    //此时即使我们定义的属性是_username,但是对外暴露的属性名其实仍然是username
    
  • 使用时等同于ngModel的形式【将父组件的username属性双向绑定到子组件上】

    <test-component [(username)]="username"></test-component>
    

五.模块的概念与划分

1.什么是模块
  • 模块就是提供相对独立功能的一组代码
  • 模块的组成部分可以有:组件、服务、指令、管道等
2.@NgModule注解
  • imports:模块依赖的其他模块**(只能导入模块)**
  • exports:暴露给其他模块使用的组件、指令或管道(可以是模块、组件、指令等)
  • providers:对于模块内部需要使用的服务
  • declarations:当前模块中有哪些组件,让模块内部组件互相知道彼此。表示模块拥有的组件、指令或管道。注意每个组件、指令、管道只能在一个模块中声明
  • bootstrap: 在根模块才有的,表示入口的组件是哪个
  • 注意:如果导入BrowserModule即可以不用导入CommonModule(其中有ngFor、ngIf等等),因为BrowserModule其中Exports包含CommonModule和ApplicationModule,导入BrowserModule相当于也导入了这两个Module
3.模块的”坑“
  • 导入其他模块时,需要知道使用该模块的目的
    • 如果是组件,那么需要在每一个需要组件的 模块都进行导入
    • 如果是服务,那么一般来说在根模块中导入一次即可
  • 需要在每个需要的模块中进行导入的
    • CommonModule:提供绑定、*ngIf*ngFor等基础指令,基本上每个模块都需要导入它
    • FormsModule、ReactiveFormsModule:表单模块需要在每一个需要的模块导入
    • 提供组件、指令或管道的模块
  • 只在跟模块导入一次的
    • HttpClientModule、BrowserAnimationsModule、NoopAnimationModule
    • 只提供服务的模块
4.有效的组织模块
  • 通常会提供一个共享模块ShareModule,用来exports公用组件一、公用组件二、公用指令一、公用指令二、公用管道一、公用管道二。从而在使用的时候直接imports共享模块即可以使用所有的内容【服务在根模块中声明】
  • 通过会提供根路由模块和根模块,在根模块中定义根组件、公共服务一、公共服务二、公共服务三等
  • 在每一个路由模块中会定义负责该模块的路由模块和当前模块,在模块中定义使用的组件、指令、管道和服务
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值