Angular通過指令動態(tài)添加組件問題
之前自己寫的公共組件,都是會先引入,需要調(diào)起的時(shí)候再通過service控制公共組件狀態(tài)、值、回調(diào)函數(shù)什么的。但是有一些場景不適合這種方式,還是動態(tài)添加組件更加好。通過寫過的一個(gè)小組件來總結(jié)下。
創(chuàng)建組件
場景:鼠標(biāo)移動到圖標(biāo)上時(shí),展示解釋性的說明文字。那就需要創(chuàng)建一個(gè)普通的tooltip組件。如下:
<aside class="hover-tip-wrapper"> <span>{{tipText}}</span> </aside>
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() { } }
.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; } }
非常簡單的一個(gè)組件,tipText來接收需要展示的文字。
需要注意的是,聲明組件的時(shí)候,除了需要添加到declarations中外,還記得要添加到entryComponents中。
entryComponents: [HovertipComponent], declarations: [HovertipComponent, HovertipDirective]
那entryComponents這個(gè)配置項(xiàng)是做什么的呢?看源碼注釋,大概意思就是:Angular會為此配置項(xiàng)中的組件創(chuàng)建一個(gè)ComponentFactory,并存放在ComponentFactoryResolver中。動態(tài)添加組件時(shí),需要用到組件工廠,所以此配置是必不可少的。
創(chuàng)建指令
通過指令為目標(biāo)元素綁定事件,控制創(chuàng)建組件、傳遞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 ) { // 獲取對應(yīng)的組件工廠 this.factory = this.resolver.resolveComponentFactory(HovertipComponent); } @Input('appHovertip') tipText: string; // 綁定鼠標(biāo)移入的事件 @HostListener('mouseenter') onmouseenter() { // 清空所有的view this.viewContainer.clear(); // 創(chuàng)建組件 this.hovertip = this.viewContainer.createComponent(this.factory); // 向組件實(shí)例傳遞參數(shù) this.hovertip.instance.tipText = this.tipText; } // 綁定鼠標(biāo)移出時(shí)的事件 @HostListener('mouseleave') onmouseleave() { if (this.hovertip) { // 組件銷毀 this.hovertip.destroy(); } } }
通過ViewContainerRef類來管理視圖,這里用到了創(chuàng)建組件。這個(gè) 專欄 解釋的挺清楚的。這里用到了以下兩個(gè)API,清除和創(chuàng)建。
createComponent方法接受ComponentFactoty類,創(chuàng)建后返回的ComponentRef類,可以獲取到組件實(shí)例(instance),控制組件銷毀。
大致思路是這樣的,先獲取到了HovertipComponent組件對于的componentFactory,監(jiān)聽鼠標(biāo)移入事件,在觸發(fā)事件時(shí),通過ViewContainerRef類來創(chuàng)建組件,存下返回的組件componentRef(獲取實(shí)例,銷毀組件時(shí)需要用到),向組件實(shí)例傳遞tipText。監(jiān)聽鼠標(biāo)移出事件,在事件觸發(fā)時(shí),銷毀組件。
使用
在目標(biāo)元素是綁定指令,同時(shí)傳遞tipText即可。
可以正常的創(chuàng)建和銷毀。
總結(jié)
開始做的時(shí)候,主要是對這幾個(gè)類比較懵,ViewContainerRef、ComponentRef、ComponentFactory、ComponentFactoryResolver等,看看源碼,查查資料,總會梳理清楚的。
參考資料:
相關(guān)文章
Angular 輸入框?qū)崿F(xiàn)自定義驗(yàn)證功能
AngularJS 表單和控件可以驗(yàn)證輸入的數(shù)據(jù)。本文給大家介紹Angular 輸入框?qū)崿F(xiàn)自定義驗(yàn)證功能,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下2017-02-02angularJs在多個(gè)控制器中共享服務(wù)數(shù)據(jù)的方法
今天小編就為大家分享一篇angularJs在多個(gè)控制器中共享服務(wù)數(shù)據(jù)的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09微信小程序?qū)崿F(xiàn)左右聯(lián)動的實(shí)戰(zhàn)記錄
聯(lián)動菜單是大家在開發(fā)小程序經(jīng)常會遇到的一個(gè)功能,下面這篇文章主要給大家介紹了關(guān)于微信小程序?qū)崿F(xiàn)左右聯(lián)動的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07Angularjs注入攔截器實(shí)現(xiàn)Loading效果
angularjs作為一個(gè)全ajax的框架,對于請求,如果頁面上不做任何操作的話,在結(jié)果反回來之前,頁面是沒有任何響應(yīng)的,不像普通的HTTP請求,會有進(jìn)度條之類2015-12-12