最近看angular2項目代碼時發(fā)現(xiàn)項目中modal的使用形式是奸柬,哪里需要modal就寫在哪里,modal嵌入在Dom樹中的很深層而不是在直接掛在body下喂柒,這樣會導致很大的問題墓卦。產(chǎn)生問題原因可以產(chǎn)看該鏈接:http://web.jobbole.com/92121/紊扬。
于是就想自己寫一個能直接在掛在body底下的modal。
那么怎么實現(xiàn)能梅垄?通過傳統(tǒng)component厂捞,其存在于component樹中顯然無法隨意改變component在樹中的結構,好在我們有dynamic component队丝,通過它我們能自主創(chuàng)建其實例并自主決定其掛載的位置靡馁,比如我們要掛載至body下。
具體實現(xiàn)如下机久,為了圖方便自己基于jquery和bootstrap3實現(xiàn)(基于原生實現(xiàn)原理相同)臭墨,原理:動態(tài)實例化組件,將組件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的實現(xiàn)所以裙犹。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 -->