我有一个指令,需要将应用它的元素移动到文档的主体:
@Directive({
selector: '[myDirective]'
})
export class MyDirective implements AfterViewInit {
constructor(private elem: ElementRef,
private renderer: Renderer2) {
}
ngAfterViewInit() {
// Move element to body
this.renderer.appendChild(document.body, this.elem.nativeElement);
}
}
Run Code Online (Sandbox Code Playgroud)
现在我在一个元素中使用这个指令ngIf,我根据一些条件进行切换:
<div myDirective *ngIf="visible">Test</div>
<button (click)="visible = !visible">Toggle</button>
Run Code Online (Sandbox Code Playgroud)
当它运行时,div将按预期显示在按钮之后,因为它被附加到正文.此时切换按钮仍然有效,我可以显示/隐藏div.
当我介绍路线时,问题出现了:
<a routerLink="/route/1">Link</a>
<div myDirective *ngIf="visible">Test</div>
<button (click)="visible = !visible">Toggle</button>
Run Code Online (Sandbox Code Playgroud)
现在,如果我显示div,并导航到另一条路线,div应该被摧毁,但它仍然可见!如果我不将div移动到身体,那么它的行为与预期的一样.
首先,我尝试删除元素,ngOnDestroy但这不适用于动画,因为它删除元素而不播放它:离开动画.
我目前的解决方法是将路由器注入指令并订阅第一个将div恢复到其原始容器的事件:
this.routerSubscription = router.events.first().subscribe(() => {
this.renderer.appendChild(this.parentNode, this.elem.nativeElement);
});
Run Code Online (Sandbox Code Playgroud)
虽然这有效,但它并不好,因为现在该指令在路由器中具有依赖性,而它应该对它一无所知.
如何改进这个黑客以确保元素被正确销毁?
演示: https ://stackblitz.com/edit/angular-qximjw?file = app%2Fapp.component.ts
要重现此问题:
您可以添加代码来删除元素ngOnDestroy:
ngOnDestroy() {
if (this.routerSubscription) {
this.routerSubscription.unsubscribe();
}
document.body.removeChild(this.elem.nativeElement);
}
Run Code Online (Sandbox Code Playgroud)
但请注意,当您导航到同一路线时,角度不会破坏它(这意味着 ngOnDestroy 不会触发)。您可以尝试添加另一条路线并导航至该路线进行确认。
请参阅演示。
| 归档时间: |
|
| 查看次数: |
2876 次 |
| 最近记录: |