1. 程式人生 > >Angular使用總結 --- 通過指令動態添加組件

Angular使用總結 --- 通過指令動態添加組件

tps header 實例 .com img app rom css 適合

  之前自己寫的公共組件,都是會先引入,需要調起的時候再通過service控制公共組件狀態、值、回調函數什麽的。但是有一些場景不適合這種方式,還是動態添加組件更加好。通過寫過的一個小組件來總結下。

創建組件

  場景:鼠標移動到圖標上時,展示解釋性的說明文字。那就需要創建一個普通的tooltip組件。如下:

技術分享圖片
<aside class="hover-tip-wrapper">
  <span>{{tipText}}</span>
</aside>
HTML 技術分享圖片
import { Component, OnInit } from ‘@angular/core‘;

@Component({
  selector: 
‘app-hovertip‘, templateUrl: ‘./hovertip.component.html‘, styleUrls: [‘./hovertip.component.scss‘] }) export class HovertipComponent implements OnInit { public tipText: string; constructor() { } ngOnInit() { } }
ts 技術分享圖片
.hover-tip-wrapper{
    width: max-content;
    position: absolute;
    height
: 30px; line-height: 30px; bottom: calc(100% + 5px); right: calc( -10px - 100%); background-color: rgba(#000000,.8); padding: 0 5px; border-radius: 3px; &::after{ content: ‘‘; position: absolute; height: 0; width: 0; border: 4px solid transparent
; border-top-color: rgba(#000000,.8); left: 10px; top: 100%; } span { color: #ccc; font-size: 12px; } }
scss

  非常簡單的一個組件,tipText來接收需要展示的文字。

  需要註意的是,聲明組件的時候,除了需要添加到declarations中外,還記得要添加到entryComponents中。

entryComponents: [HovertipComponent],
declarations: [HovertipComponent, HovertipDirective]

  那entryComponents這個配置項是做什麽的呢?看源碼註釋,大概意思就是:Angular會為此配置項中的組件創建一個ComponentFactory,並存放在ComponentFactoryResolver中。動態添加組件時,需要用到組件工廠,所以此配置是必不可少的。

技術分享圖片

創建指令

  通過指令為目標元素綁定事件,控制創建組件、傳遞tipText以及組件的銷毀。

import { Input , Directive , ViewContainerRef , ComponentRef, ComponentFactory, HostListener , ComponentFactoryResolver} from ‘@angular/core‘;
import { HovertipComponent } from ‘./hovertip.component‘;
@Directive({
  selector: ‘[appHovertip]‘
})
export class HovertipDirective {

  public hovertip: ComponentRef<HovertipComponent>;
  public factory: ComponentFactory<HovertipComponent>;
  constructor(
    private viewContainer: ViewContainerRef,
    private resolver: ComponentFactoryResolver
  ) {
// 獲取對應的組件工廠
this.factory = this.resolver.resolveComponentFactory(HovertipComponent); } @Input(‘appHovertip‘) tipText: string;  
// 綁定鼠標移入的事件 @HostListener(
‘mouseenter‘) onmouseenter() {
   // 清空所有的view
  
this.viewContainer.clear();
// 創建組件
this.hovertip = this.viewContainer.createComponent(this.factory);
// 向組件實例傳遞參數
this.hovertip.instance.tipText = this.tipText; }  
 // 綁定鼠標移出時的事件 @HostListener(
‘mouseleave‘) onmouseleave() { if (this.hovertip) {
  // 組件銷毀
this.hovertip.destroy(); } } }

  

  通過ViewContainerRef類來管理視圖,這裏用到了創建組件。這個 專欄 解釋的挺清楚的。這裏用到了以下兩個API,清除和創建。

  

技術分享圖片

  

  createComponent方法接受ComponentFactoty類,創建後返回的ComponentRef類,可以獲取到組件實例(instance),控制組件銷毀

技術分享圖片

  大致思路是這樣的,先獲取到了HovertipComponent組件對於的componentFactory,監聽鼠標移入事件,在觸發事件時,通過ViewContainerRef類來創建組件,存下返回的組件componentRef(獲取實例,銷毀組件時需要用到),向組件實例傳遞tipText。監聽鼠標移出事件,在事件觸發時,銷毀組件。

使用

  在目標元素是綁定指令,同時傳遞tipText即可。技術分享圖片

  可以正常的創建和銷毀。

技術分享圖片

總結

  開始做的時候,主要是對這幾個類比較懵,ViewContainerRef、ComponentRef、ComponentFactory、ComponentFactoryResolver等,看看源碼,查查資料,總會梳理清楚的。

  參考資料:

   https://segmentfault.com/a/1190000008672478#articleHeader1

   https://segmentfault.com/a/1190000009175508

Angular使用總結 --- 通過指令動態添加組件