最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Angular使用動態(tài)加載組件方法實現(xiàn)Dialog的示例

 更新時間:2018年05月11日 09:38:32   作者:bugDeveloper  
這篇文章主要介紹了Angular使用動態(tài)加載組件方法實現(xiàn)Dialog的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

網(wǎng)上的文章和教程基本上寫到組件加載完成就沒了!沒了?!而且都是只能存在一個dialog,想要打開另一個dialog必須先銷毀當(dāng)前打開的dialog,之后看過 material 的實現(xiàn)方式,怪自己太蠢看不懂源碼,就只能用自己的方式來實現(xiàn)一個dialog組件了

Dialog組件的目標(biāo):可以同時存在多個Dialog,可銷毀指定Dialog,銷毀后html中無組件殘留且提供回調(diào)

動態(tài)加載組件的實現(xiàn)方式有兩種,angular4.0版本之前使用ComponentFactoryResolver來實現(xiàn),4.0之后可以使用更便捷的ngComponentOutlet來實現(xiàn),

通過ComponentFactoryResolver實現(xiàn)動態(tài)載入

首先理一下ViewChild、ViewChildren、ElementRef、ViewContainerRef、ViewRef、ComponentRef、ComponentFactoryResolver之間的關(guān)系:

ViewChild 與 ViewChildren

ViewChild是通過模板引用變量(#)或者指令(directive)用來獲取 Angular Dom 抽象類,ViewChild可以使用 ElementRef 或者 ViewContainerRef 進行封裝。

@ViewChild('customerRef') customerRef:ElementRef;

ViewChildren通過模板引用變量或者指令用來獲取QueryList,像是多個ViewChild組成的數(shù)組。

@ViewChildren(ChildDirective) viewChildren: QueryList<ChildDirective>;

ElementRef 與 ViewContainerRef

ViewChild可以使用 ElementRef 或者 ViewContainerRef 進行封裝,那么 ElementRef 和 ViewContainerRef 的區(qū)別是什么?

用 ElementRef 進行封裝,然后通過 .nativeElement 來獲取原生Dom元素

console.log(this.customerRef.nativeElement.outerHTML);

ViewContainerRef :視圖的容器,包含創(chuàng)建視圖的方法和操作視圖的api(組件與模板共同定義了視圖)。api會返回 ComponentRef 與 ViewRef,那么這兩個又是什么?

// 使用ViewContainetRef時,請使用read聲明
@ViewChild('customerRef',{read: ViewContainerRef}) customerRef:ViewContainerRef;
···
this.customerRef.createComponent(componentFactory) // componentFactory之后會提到

ViewRef 與 ComponentRef

ViewRef 是最小的UI單元,ViewContainerRef api操作和獲取的就是ViewRef

ComponentRef:宿主視圖(組件實例視圖)通過 ViewContainerRef 創(chuàng)建的對組件視圖的引用,可以獲取組件的信息并調(diào)用組件的方法

ComponentFactoryResolver

要獲取 ComponentRef ,需要調(diào)用 ViewContainer 的 createComponent 方法,方法需要傳入ComponentFactoryResolver創(chuàng)建的參數(shù)

constructor(
 private componentFactoryResolver:ComponentFactoryResolver
) { }

viewInit(){
  componentFactory = 
   this.componentFactoryResolver.resolveComponentFactory(DialogComponent);
  // 獲取對組件視圖的引用,到這一步就已經(jīng)完成了組件的動態(tài)加載
  componentRef = this.customerRef.createComponent(componentFactory);
  // 調(diào)用載入的組件的方法
  componentRef.instance.dialogInit(component);
}

具體實現(xiàn)

let componentFactory,componentRef;

@ViewChild('customerRef',{read: ViewContainerRef}) customerRef:ViewContainerRef;
constructor(
 private componentFactoryResolver:ComponentFactoryResolver
) { }

viewInit(){
 // DialogComponent:你想要動態(tài)載入的組件,customerRef:動態(tài)組件存放的容器
  componentFactory = 
   this.componentFactoryResolver.resolveComponentFactory(DialogComponent);
  componentRef = this.customerRef.createComponent(componentFactory);
}

通過ngComponentOutlet實現(xiàn)動態(tài)載入

ngComponentOutlet 大大縮減了代碼量,但是只有帶4.0之后的版本才支持

具體實現(xiàn)

在dialog.component.html建立動態(tài)組件存放節(jié)點

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

將組件(不是組件名稱)傳入,就OK了,為什么可以這么簡單!

dialogInit(component){
  this.componentName = component;
};

Dialog的實現(xiàn)

實現(xiàn)的思路是這樣的:首先創(chuàng)建一個dialog組件用來承載其他組件,為dialog創(chuàng)建遮罩和動畫,建立一個service來控制dialog的生成和銷毀,不過service只生成dialog,dialog內(nèi)的組件還是需要在dialog組件內(nèi)進行生成

1、首先寫一個公共的service,用來獲取根組件的viewContainerRef(嘗試過 ApplicationRef 獲取根組件的 viewContainerRef 沒成功,所以就寫成service了)

gerRootNode(...rootNodeViewContainerRef){
  if(rootNode){
   return rootNode;
  }else {
   rootNode = rootNodeViewContainerRef[0];
  };
}

// 然后再根組件.ts內(nèi)調(diào)用
this.fn.gerRootNode(this.viewcontainerRef);

2、創(chuàng)建dialog.service.ts,定義open、close三個方法,使用ViewContainerRef創(chuàng)建dialog組件,創(chuàng)建之前需要調(diào)用 ComponentFactoryReslover,并將DialogComponent傳入

let componentFactory;
let componentRef;

@Injectable()
export class DialogService {
 constructor(
    private componentFactoryResolver:ComponentFactoryResolver
    private fn:FnService
  ) { }   

 open(component){
  componentFactory = 
   this.componentFactoryResolver.resolveComponentFactory(DialogComponent);
  
  // 這里的獲取的是ComponentRef
  containerRef = this.fn.gerRootNode().createComponent(componentFactory); 
  
  // 將containerRef存儲下來,以便之后的銷毀
  containerRefArray.push(containerRef);
  
  // 調(diào)用了組件內(nèi)的初始化方法,后面會提到
  return containerRef.instance.dialogInit(component,containerRef);
 }

  // 這里有兩種情況,一種是在當(dāng)前組件和dialog組件關(guān)閉調(diào)用的,因為有返回值所以可以關(guān)閉指定的dialog;還有一種是在插入到dialog組件內(nèi)的組件調(diào)用的,因為不知道父組件的信息,所以默認關(guān)閉最后一個dialog
 close(_containerRef=null){
  if( _containerRef ){
   return _containerRef.containerRef.instance.dialogDestory();
  }else{
   containerRefArray.splice(-1,1)[0].instance.dialogDestory();
  }
 }

}

3、dialog.component.ts,這里使用 ngComponentOutlet 來實現(xiàn)(ngComponentOutlet 在下面提到,這里為了偷懶,直接拿來用了)

let containerRef,dialogRef = new DialogRef();

export class DialogComponent implements OnInit {

 componentName;
 constructor(
  private fn:FnService
 ) { }

 dialogInit( _component, _containerRef){
  this.componentName = _component;
  containerRef = _containerRef;
  dialogRef['containerRef'] = containerRef;
  return dialogRef;
 };

 dialogDestory(){
  let rootNode = this.fn.gerRootNode();
  // 等待動畫結(jié)束再移除
  setTimeout(()=>{
  // 這里用到了 viewContainerRef 里的indexOf 和 remove 方法
   rootNode.remove(rootNode.indexOf(containerRef.hostView));
  },400);
  dialogRef.close();
  return true;
 };
 
}

4、這里還創(chuàng)建了一個 DialogRef 的類,用來處理 dialog 關(guān)閉后的回調(diào),這樣就可以使用 XX.afterClose().subscribe() 來創(chuàng)建回調(diào)的方法了

@Injectable()
export class DialogRef{

 public afterClose$ = new Subject();
 constructor(){}

 close(){
  this.afterClose$.next();
  this.afterClose$.complete();
 }

 afterClose(){
  return this.afterClose$.asObservable();
 }

}

創(chuàng)建和銷毀dialog

// 創(chuàng)建
let _viewRef = this.dialogService.open(DialogTestComponent);
_viewRef.afterClose().subscribe(()=>{
  console.log('hi');
});

// 銷毀
this.dialogService.close()

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解AngularJS如何實現(xiàn)跨域請求

    詳解AngularJS如何實現(xiàn)跨域請求

    跨域請求一直是網(wǎng)頁編程中的一個難題,在過去,絕大多數(shù)人都傾向于使用JSONP來解決這一問題。不過現(xiàn)在,我們可以考慮一下W3C中一項新的特性——CORS(Cross-Origin Resource Sharing)了。
    2016-08-08
  • AngularJS入門教程一:路由用法初探

    AngularJS入門教程一:路由用法初探

    這篇文章主要介紹了AngularJS路由用法,簡單分析了AngularJS路由的概念、功能及基本使用方法,需要的朋友可以參考下
    2017-05-05
  • Angularjs實現(xiàn)多圖片上傳預(yù)覽功能

    Angularjs實現(xiàn)多圖片上傳預(yù)覽功能

    這篇文章主要介紹了Angularjs實現(xiàn)多圖片上傳預(yù)覽功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • AngularJS  雙向數(shù)據(jù)綁定詳解簡單實例

    AngularJS 雙向數(shù)據(jù)綁定詳解簡單實例

    這篇文章主要介紹了AngularJS 雙向數(shù)據(jù)綁定詳解簡單實例的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • angular *Ngif else用法詳解

    angular *Ngif else用法詳解

    這篇文章主要介紹了angular *Ngif else用法詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • 詳解Angular的內(nèi)置過濾器和自定義過濾器【推薦】

    詳解Angular的內(nèi)置過濾器和自定義過濾器【推薦】

    在實際的開發(fā)過程中,很多后端返回給我們的數(shù)據(jù)都是需要格式化處理的,在angular中為我們內(nèi)置提供了filter指令,可以很方便的對數(shù)據(jù)進行處理。本文將對Angular的內(nèi)置過濾器和自定義過濾器進行詳細介紹,下面跟著小編一起來看下吧
    2016-12-12
  • 淺談Angular路由復(fù)用策略

    淺談Angular路由復(fù)用策略

    本篇文章主要介紹了淺談Angular路由復(fù)用策略,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • AngularJS過濾器filter用法分析

    AngularJS過濾器filter用法分析

    這篇文章主要介紹了AngularJS過濾器filter用法,結(jié)合實例形式分析了過濾器filter的功能、分類、使用方法與相關(guān)注意事項,需要的朋友可以參考下
    2016-12-12
  • angularjs實現(xiàn)與服務(wù)器交互分享

    angularjs實現(xiàn)與服務(wù)器交互分享

    AngularJS是Google開發(fā)的純客戶端JavaScript技術(shù)的WEB框架,用于擴展、增強HTML功能,它專為構(gòu)建強大的WEB應(yīng)用而設(shè)計。
    2014-06-06
  • 淺談angularJS2中的界面跳轉(zhuǎn)方法

    淺談angularJS2中的界面跳轉(zhuǎn)方法

    今天小編就為大家分享一篇淺談angularJS2中的界面跳轉(zhuǎn)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-08-08

最新評論

嘉荫县| 宁乡县| 武宁县| 香格里拉县| 山阴县| 阿克陶县| 承德市| 屏山县| 贵德县| 通海县| 灯塔市| 怀集县| 禄丰县| 改则县| 呼和浩特市| 双鸭山市| 六枝特区| 民乐县| 中西区| 临夏市| 聂荣县| 济南市| 张家港市| 湖北省| 太和县| 盐城市| 闻喜县| 海原县| 蒲江县| 太湖县| 赤城县| 深水埗区| 佛山市| 江都市| 剑阁县| 石楼县| 桐梓县| 庆元县| 安塞县| 宜良县| 丰台区|