angular2.0

如何实现angular2版本的modal弹框

2018-01-25  本文已影响416人  前端大魔王

最近看angular2项目代码时发现项目中modal的使用形式是,哪里需要modal就写在哪里,modal嵌入在Dom树中的很深层而不是在直接挂在body下,这样会导致很大的问题。产生问题原因可以产看该链接:http://web.jobbole.com/92121/

于是就想自己写一个能直接在挂在body底下的modal。

那么怎么实现能?通过传统component,其存在于component树中显然无法随意改变component在树中的结构,好在我们有dynamic component,通过它我们能自主创建其实例并自主决定其挂载的位置,比如我们要挂载至body下。

具体实现如下,为了图方便自己基于jquery和bootstrap3实现(基于原生实现原理相同),原理:动态实例化组件,将组件dom挂至body下。删除时destroy component ,移除dom

import {
  ComponentFactoryResolver,
  ComponentRef,
  ReflectiveInjector,
  ApplicationRef,
  Injectable,
  EventEmitter,
} from '@angular/core';
@Injectable()
export class ModalService {
  private modals: Modal[] = [];
  constructor(private componentFactoryResolver: ComponentFactoryResolver,
              private applicationRef: ApplicationRef) { }

  create(component) {
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(component);
    const injector = ReflectiveInjector.resolveAndCreate([]);
    const componentRef = componentFactory.create(injector);
    this.applicationRef.attachView(componentRef.hostView);
    document.body.appendChild(componentRef.location.nativeElement);
    const modal = new Modal(componentRef);
    this.modals.push(modal);
    return modal;
  }
  destory(modal: Modal) {
    modal.hide();
    this.modals.splice(this.modals.indexOf(modal), 1);
    modal.$el.remove();
    modal.componentRef.destroy();
  }
}

export class Modal {
  $el;
  $modalEl;
  public componentRef;
  public onShown = new EventEmitter();
  public onHidden = new EventEmitter();
  constructor(componentRef) {
    this.$el = $(componentRef.location.nativeElement);
    this.$modalEl = this.$el.find('.modal');
    this.componentRef = componentRef;
    this.$modalEl.on('shown.bs.modal', (e)=>{
      this.onShown.emit(e);
    });
    this.$modalEl.on('hidden.bs.modal',(e)=>{
      this.onHidden.emit(e);
    });
  }
  show() {
    this.$modalEl.modal('show');
  }
  hide() {
    this.$modalEl.modal('hide');
  }
}

使用

 this.modal = this.modal || this.modalService.create(SelectDeviceModalComponent);
    this.modal.show();
    this.modal.onHidden.subscribe((e) => {
      this.modalService.destory(this.modal);
      this.modal = null;
    });

注意由于是基于bootstrap的实现所以。create中传的组件的html必须是bootstrap的modal形式,例如:

<div class="modal fade" tabindex="-1" role="dialog" aria-labelledby="gridSystemModalLabel">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
        <h4 class="modal-title" id="gridSystemModalLabel">Modal title</h4>
      </div>
      <div class="modal-body">
       
      </div>
      <div class="modal-footer">

      </div>
    </div><!-- /.modal-content -->
  </div><!-- /.modal-dialog -->
</div><!-- /.modal -->
上一篇下一篇

猜你喜欢

热点阅读