Angular 组件之动态组件 | 更文挑战第5天

310 阅读2分钟

这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战

1. 写一个动态组件

动态组件的写法和普通组件没区别

...
@Component({
  selector: 'login',
})
export class LoginComponent {}

2. 申明方式

需要在模块的entryComponents中申明下

@NgModule({
    declarations: [LoginComponent],
    entryComponents: [LoginComponent]
})

3. 使用方式上很大区别

3.1 方式1

ts

import { LoginComponent } from 'xxx';
...
export class UserComponent{
    loginComponent = LoginComponent;
}

html

<ng-container *ngComponentOutlet="loginComponent"></ng-container>

3.2 方式2

html

<ng-template #loginContainer></ng-template>

ts

import { ComponentFactory, ComponentFactoryResolver, OnInit,  ViewChild, ViewContainerRef } from '@angular/core';
import { loginComponent } from 'xxx';

export class UserComponent{
   loginRef;
   @ViewChild('loginContainer', { read: ViewContainerRef, static: true }) 
   loginContainer: ViewContainerRef;

   constructor(private cfr: ComponentFactoryResolver){}
   
    ngOnInit() {
        this.loginContainer.clear();
        const factory: ComponentFactory<any> = this.cfr.resolveComponentFactory(loginComponent);
        this.loginRef = this.loginContainer.createComponent(factory);
    }
    
    ngOnDestroy(){
        // 组件卸载的时候 动态组件也需要卸载
        if(this.loginRef){
            this.loginRef.destroy() 
        }
    }
}

4. 动态组件传参和事件触发

ngOnInit() {
    this.loginContainer.clear();
    const factory: ComponentFactory<any> = this.cfr.resolveComponentFactory(loginComponent);
    this.loginRef = this.loginContainer.createComponent(factory);
}

@Input传参
this.loginRef.instance是获取组件的实例,someInputProp是组件中@input 接收的参数。

this.loginRef.instance.someInputProp = value;

Output绑定 this.loginRef.instance是获取组件的实例,someOutput是组件中@Output 触发的函数。

this.loginRef.instance.someOutput.subscribe(data => {});

彩蛋

1. Angular如何主动销毁组件

使用remove函数,它不会触发组件的生命周期,还得手动调用ngOnDestroy

constructor(private element: ElementRef) {} 

// 你要销毁的时候调用它
triggerDestroy(){
    this.element.nativeElement.remove(); 
    this.ngOnDestroy() 
}

2. Angular 组件监听传过来值变化的若干姿势

使用Onchanges生命周期监听值变化

import { Input, OnChanges, SimpleChanges } from '@angular/core';
...
export class xxx implements OnChanges {
  @Input() title: string;
  
  ngOnChanges(sc: SimpleChanges) {
    if('title' in sc){ // 需要做存在判断才能使用
        // sc.title.currentValue --> 最新的值,做一些处理逻辑
    } 
  }
}

使用 get、set 方式监听

import { Input } from '@angular/core';
...
export class xxx implements OnChanges {
   _title: string;
  @Input()
  get title() {
    return this._title;
  }
  set title(value) {
    // 做一些处理逻辑
    this._title = value;
  }
}

传过来的值若为引用类型,只是改变属性,引用不变上述方法均不会触发,建议传过来的时候深拷贝一下

3. Angular 如何将字符串的html渲染到dom元素中

<div [innerHTML]="theHtmlString"></div>

更多用法更新于 github