如何实现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">×</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 -->