成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

Angular4 動(dòng)態(tài)加載組件雜談

testHs / 1662人閱讀

摘要:最近接手了一個(gè)項(xiàng)目,客戶(hù)提出了一個(gè)高大上的需求要求只有一個(gè)主界面,所有組件通過(guò)來(lái)顯示。

最近接手了一個(gè)項(xiàng)目,客戶(hù)提出了一個(gè)高大上的需求:要求只有一個(gè)主界面,所有組件通過(guò)Tab來(lái)顯示。其實(shí)這個(gè)需求并不詭異,不喜歡界面跳轉(zhuǎn)的客戶(hù)都非常熱衷于這種展現(xiàn)形式。

好吧,客戶(hù)至上,搞定它!這種實(shí)現(xiàn)方式在傳統(tǒng)的HTML應(yīng)用中,非常簡(jiǎn)單,只是在這Angular4(以下簡(jiǎn)稱(chēng)ng)中,咋個(gè)弄呢?

我們先來(lái)了解下ng中動(dòng)態(tài)加載組件的兩種方式:

加載已經(jīng)聲明的組件: 使用ComponentFactoryResolver,將一個(gè)組件實(shí)例呈現(xiàn)到另一個(gè)組件視圖上;

動(dòng)態(tài)創(chuàng)建組件并加載:使用ComponentFactory和Compiler,創(chuàng)建和呈現(xiàn)組件

根據(jù)我們的需求,各個(gè)組件是事先開(kāi)發(fā)好的,需要在同一個(gè)組件上顯示出來(lái)。所以第一種方式符合我們的要求。

使用ComponentFactoryResolver動(dòng)態(tài)加載組件,需要先了解如下概念:

ViewChild:屬性裝飾器,通過(guò)它可以獲得視圖上對(duì)應(yīng)的元素;

ViewContainerRef:視圖容器,可在其上創(chuàng)建、刪除組件;

ComponentFactoryResolver:組件解析器,可以將一個(gè)組件呈現(xiàn)在另一個(gè)組件的視圖上。

搞明白了概念,看看代碼吧:

//// HTML代碼
//// ts代碼
import {Component, Input, ViewContainerRef, ViewChild, ComponentFactoryResolver,ComponentRef,OnDestroy,OnInit} from "@angular/core";
import {RoleComponent} from "./role/role.component";
@Component({
   selector: "dynamic-container",
   entryComponents: [RoleComponent,....],  //需要?jiǎng)討B(tài)加載的組件名,這里一定要指定,否則報(bào)錯(cuò)
   template: ""
})
export class DynamicComponent implements OnDestroy,OnInit {
    @ViewChild("container", { read: ViewContainerRef }) container: ViewContainerRef;
    @Input() componentName      //需要加載的組件名
    compRef: ComponentRef; //  加載的組件實(shí)例
    constructor(private resolver: ComponentFactoryResolver) {}
    loadComponent() {
       let factory = this.resolver.resolveComponentFactory(this.componentName);
       if (this.compRef) {
         this.compRef.destroy();
        }
       this.compRef = this.container.createComponent(factory) //創(chuàng)建組件
     }
    ngAfterContentInit() {
       this.loadComponent()
    }
    ngOnDestroy() {
       if(this.compRef){
          this.compRef.destroy();
       }
    }
}

代碼的確不復(fù)雜!

可是,如果加載的組件有傳入的參數(shù),比如修改角色組件,需要傳入角色id,該怎么辦呢?有辦法解決,使用ReflectiveInjector(依賴(lài)注入),在加載組件時(shí)將需要傳入的參數(shù)注入到組件中。代碼調(diào)整如下:

//// HTML代碼,增加了inputs參數(shù),其值為參數(shù)值對(duì)
//// ts代碼
import { ReflectiveInjector} from "@angular/core";
......
export class DynamicComponent implements OnDestroy,OnInit {
    
    @Input() inputs:any         //加載組件需要傳入的參數(shù)組
    .......
    loadComponent() {
       let factory = this.resolver.resolveComponentFactory(this.componentName);
     
       if(!this.inputs)
          this.inputs={}
   
       let inputProviders = Object.keys(this.inputs).map((inputName) => {
           return {provide: inputName, useValue: this.inputs[inputName]};});
    
       let resolvedInputs = ReflectiveInjector.resolve(inputProviders);
    
    
       let injector = ReflectiveInjector.fromResolvedProviders(resolvedInputs, this.container.parentInjector);
    
       if (this.compRef) {
         this.compRef.destroy();
        }
       this.compRef = factory.create(injector) //創(chuàng)建帶參數(shù)的組件
       this.container.insert(this.compRef.hostView);//呈現(xiàn)組件的視圖
  }
  ngAfterContentInit() {
    this.loadComponent()
  }
  ......
}
////RoleComponent代碼如下
export class RoleComponent implements OnInit {
    myName:string
    ........
    constructor(){
        //this.myName的值為dynamic
   }
}

到此,動(dòng)態(tài)加載組件的界面驕傲滴顯示在界面上。等等,貌似哪里不對(duì)!為什么界面上從后臺(tái)獲取的數(shù)據(jù)沒(méi)有加載?

獲取數(shù)據(jù)的代碼如下:

export class RoleComponent implements OnInit {
   roleList=[];
   ......
   constructor(private _roleService.list:RoleService) {
      this._roleService.list().subscribe(res=>{
          this.roleList=res.roleList;
      });
   }
   ......
}

經(jīng)過(guò)反復(fù)測(cè)試,得出結(jié)論如下:從后臺(tái)通過(guò)HTTP獲取的數(shù)據(jù)已經(jīng)獲得,只是沒(méi)有觸發(fā)ng進(jìn)行變更檢測(cè),所以界面沒(méi)有渲染出數(shù)據(jù)。

抱著“遇坑填坑”的信念,研習(xí)ng的文檔,發(fā)現(xiàn)ng支持手動(dòng)觸發(fā)變更檢測(cè),只要在適當(dāng)?shù)奈恢谜{(diào)用變更檢測(cè)即可。同時(shí),ng提供了不同級(jí)別的變更檢測(cè):

變更檢測(cè)策略:

Default :ng提供的Default的檢測(cè)策略,只要組件的input發(fā)生改變,就觸發(fā)檢測(cè);
  OnPush :OnPush檢測(cè)策略是input發(fā)生改變,并不立即觸發(fā)檢測(cè),而是輸入的引用發(fā)生變化時(shí),才會(huì)觸發(fā)檢測(cè)。

ChangeDetectorRef.detectChanges():可顯式的控制變更檢測(cè),在需要的地方使用即可;

NgZone.run():在整個(gè)應(yīng)用中進(jìn)行變更檢測(cè)

ApplicationRef.tick():在整個(gè)應(yīng)用中進(jìn)行變更檢測(cè),偵聽(tīng)NgZone的onTurnDone事件,來(lái)觸發(fā)檢測(cè)

根據(jù)文檔顯示,ng應(yīng)用缺省就在使用NgZone來(lái)檢測(cè)變更,這對(duì)于正常加載的組件是沒(méi)有問(wèn)題的,但是對(duì)于動(dòng)態(tài)加載的組件卻不起作用。幾次試驗(yàn)下來(lái),唯有第二種方法起作用:顯式調(diào)用ChangeDetectorRef.detectChanges()

于是修改ts代碼:

interval:any 
loadComponent() {
    ......
    this.interval=setInterval(() => {
      this.compRef.changeDetectorRef.detectChanges();
    }, 50);  //50毫秒檢測(cè)一次變更
}
ngOnDestroy() {
    ......
    clearInterval(this.interval)
}

鑒于本人的ng技能尚淺,就用這種笨拙的方法解決了數(shù)據(jù)加載問(wèn)題,但是如鯁在喉,總覺(jué)應(yīng)該還有更優(yōu)雅的解決方法,待我再花時(shí)日研究下。

啰嗦至此,文中如有不妥之處,歡迎各位看官指正。

補(bǔ)充一句,強(qiáng)烈推薦PrimeNG,它提供了豐富的前端組件,可以方便取用,大大節(jié)省了界面的開(kāi)發(fā)速度。

參考文獻(xiàn):

Angular 2 Change Detection, Zones and an example

Angular change detection explained

深入理解Angular2變化監(jiān)測(cè)和ngZone

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/83891.html

相關(guān)文章

  • Angular2 VS Angular4 深度對(duì)比:特性、性能

    摘要:的特性和性能是的超集,用于幫助的開(kāi)發(fā)。注解提供了連接元數(shù)據(jù)和功能的工具。通過(guò)在庫(kù)中提供基本信息可以調(diào)用函數(shù)或創(chuàng)建類(lèi)的實(shí)例來(lái)檢查相關(guān)元數(shù)據(jù),從而簡(jiǎn)化了對(duì)象實(shí)例的構(gòu)建。停用它會(huì)響應(yīng)跳出舊控制器的成功事件。 showImg(https://segmentfault.com/img/bVSqTU?w=850&h=460); 在Web應(yīng)用開(kāi)發(fā)領(lǐng)域,Angular被認(rèn)為是最好的開(kāi)源JavaScri...

    孫淑建 評(píng)論0 收藏0
  • 雜談 CSS IN JS

    摘要:缺乏高級(jí)編程特性影響同樣深遠(yuǎn),社區(qū)發(fā)展的預(yù)處理器能夠有效緩解,,,殊途同歸,異軍突起,基本實(shí)現(xiàn)變量嵌套變量混合擴(kuò)展和邏輯等。 前言 關(guān)注點(diǎn)分離(separation of concerns)原則多年來(lái)大行其道,實(shí)踐中一般將 HTML、CSS、JavaScript 分開(kāi)編寫(xiě)維護(hù),早期框架 angularjs 即是如此,直到 React 爭(zhēng)議中問(wèn)世,引領(lǐng)關(guān)注點(diǎn)混合趨勢(shì),驅(qū)使開(kāi)發(fā)者重新審視 ...

    Nosee 評(píng)論0 收藏0
  • 前端模塊化雜談

    摘要:并不是使用安裝的模塊我們就可以使用同樣的方式使用任何一個(gè)模塊,使用某種工具將這些模塊打包發(fā)布作為事實(shí)上的前端模塊化標(biāo)準(zhǔn),或可以出來(lái)解救我們。目前比較拿的出手的,也就是的模塊化,比如或者等等,分別可以使用和。 Teambition是一家追求卓越技術(shù)的公司,我們工程師都很Geek,我們使用了很多新潮的,開(kāi)源的技術(shù)。同時(shí)我們也貢獻(xiàn)了很多開(kāi)源的項(xiàng)目。我們希望能夠把一些技術(shù)經(jīng)驗(yàn)分享給大家。...

    yacheng 評(píng)論0 收藏0
  • 前端模塊化雜談

    摘要:并不是使用安裝的模塊我們就可以使用同樣的方式使用任何一個(gè)模塊,使用某種工具將這些模塊打包發(fā)布作為事實(shí)上的前端模塊化標(biāo)準(zhǔn),或可以出來(lái)解救我們。目前比較拿的出手的,也就是的模塊化,比如或者等等,分別可以使用和。 Teambition是一家追求卓越技術(shù)的公司,我們工程師都很Geek,我們使用了很多新潮的,開(kāi)源的技術(shù)。同時(shí)我們也貢獻(xiàn)了很多開(kāi)源的項(xiàng)目。我們希望能夠把一些技術(shù)經(jīng)驗(yàn)分享給大家。...

    li21 評(píng)論0 收藏0
  • 利用angular4和nodejs-express構(gòu)建一個(gè)簡(jiǎn)單的網(wǎng)站(六)—用戶(hù)模塊和路由分析

    摘要:上一節(jié)解決了用戶(hù)注冊(cè)和登錄數(shù)據(jù)部分的內(nèi)容。這一節(jié)開(kāi)始分析用戶(hù)模塊用戶(hù)路由。用戶(hù)管理模塊分析主要代碼如下數(shù)組中,是構(gòu)建子組件必須引入的模塊。當(dāng)點(diǎn)擊標(biāo)簽時(shí),根據(jù)路由定義直接跳轉(zhuǎn)到組件,進(jìn)行用戶(hù)的注冊(cè)操作。 上一節(jié)解決了用戶(hù)注冊(cè)和登錄數(shù)據(jù)部分的內(nèi)容。這一節(jié)開(kāi)始分析用戶(hù)模塊、用戶(hù)路由。## 用戶(hù)管理模塊UserModule分析 ##UserModule主要代碼如下: import { NgMo...

    cfanr 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<