在我们的代码库中,我们有一个虚拟重复指令,它使用Renderer2来创建一个这样的div:
this.renderer2.createElement('div');
Run Code Online (Sandbox Code Playgroud)
在ngOnDestroy方法中,我们像这样销毁它:
this.renderer.destroyNode(this.offsetBeforeEl);
Run Code Online (Sandbox Code Playgroud)
这工作正常,我们没有问题,直到我们在prod模式下构建应用程序,我们开始收到以下错误:
main.js?d73b003…:formatted:87193 Uncaught (in promise) TypeError: this.renderer.destroyNode is not a function
Run Code Online (Sandbox Code Playgroud)
我在该行添加了一个断点,发现实际上destroyNode不是Renderer2上的方法.我去了angular的源代码,并在抽象类定义中找到了方法上方的注释:
/**
* This property is allowed to be null / undefined,
* in which case the view engine won't call it.
* This is used as a performance optimization for production mode.
*/
destroyNode: ((node: any) => void)|null;
Run Code Online (Sandbox Code Playgroud)
所以我检查了视图的代码并看到了这个:
if (view.renderer.destroyNode) {
destroyViewNodes(view);
}
if (isComponentView(view)) {
view.renderer.destroy();
}
Run Code Online (Sandbox Code Playgroud)
如果我不能依赖现有的方法,那么破坏使用Renderer2动态创建的节点的正确方法是什么?
使用renderer.removeChild
方法。
直到我们以生产模式构建应用程序
destroyNode
方法在DebugRenderer2上定义,在生产模式下不使用。
可以从angular的处理方式中推断出处理节点删除的正确方法,例如,以下execRenderNodeAction函数:
function execRenderNodeAction(
view: ViewData, renderNode: any, action: RenderNodeAction, parentNode: any, nextSibling: any,
target?: any[]) {
const renderer = view.renderer;
switch (action) {
case RenderNodeAction.RemoveChild:
renderer.removeChild(parentNode, renderNode);
break;
Run Code Online (Sandbox Code Playgroud)
因此,使用removeChild
像这样:
const parent = this.renderer.createElement('div');
const child = this.renderer.createElement('span');
this.renderer.appendChild(parent, child);
// using remove child
this.renderer.removeChild(parent, child);
Run Code Online (Sandbox Code Playgroud)
要删除所有子项,您必须遍历子项元素。请注意,这children
不是真正的数组,因此必须先进行转换。
Array.from(this.elementRef.nativeElement.children).forEach(child => {
console.log('children.length=' + this.elementRef.nativeElement.children.length);
this.renderer.removeChild(this.elementRef.nativeElement, child);
});
Run Code Online (Sandbox Code Playgroud)
日志记录语句表明,实际上并没有实时地从DOM中实时删除子级-这就是为什么while循环无法删除的原因lastChild
。
如果这些元素不是您最初添加的,请格外小心-因为如果它们是组件,则可能会导致内存泄漏或各种怪异现象。上面仅测试了将自己添加到空元素节点中的元素。
我认为我应该可以[...this.elementRef.nativeElement.children]
,但是抱怨slice
并不存在-所以我回复到Array.from
。
归档时间: |
|
查看次数: |
8353 次 |
最近记录: |