ViewDestroyedError:尝试使用被破坏的视图:detectChanges [英] ViewDestroyedError: Attempt to use a destroyed view: detectChanges

查看:31
本文介绍了ViewDestroyedError:尝试使用被破坏的视图:detectChanges的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下组件可以创建一个 MdDialog

I have the following component that creates an MdDialog

export class SideNavsComponent implements OnInit, AfterViewInit, OnDestroy {
  eventDispatcher: EventDispatcher
  authEmailDialogRef: MdDialogRef<AuthEmailDialogComponent>

  constructor(public dialog: MdDialog,) {
    this.eventDispatcher = new EventDispatcher()
  }

  signIn( event ): void {
    this.isSignedIn = event.checked
    this.openDialog()
  }

  openDialog() {
    this.authEmailDialogRef = this.dialog.open( AuthEmailDialogComponent, {
      height: '500px',
      width: '300px',
      disableClose: true
    } )
  }

  ngOnDestroy() {
  }

  ngAfterViewInit() {
  }

  ngOnInit() {
    event_dispatcher.on( 'CLOSE authEmailDialogRef', ( target: Object ) => {
      this.authEmailDialogRef.close()
    } )
  }
}

下面的组件创建一个按钮,当点击该按钮时,通过发送和在 SideNavsComponent#ngOnInit 方法中拦截的事件关闭上面创建的 MdDialog

The component below creates a button that when clicked closes the MdDialog created above by sending and event that is intercepted within the SideNavsComponent#ngOnInit method

export class AuthEmailDialogComponent implements OnInit {
eventDispatcher: EventDispatcher = new EventDispatcher()
}

cancel() {
      event_dispatcher.dispatch( 'CLOSE authEmailDialogRef', '')
  }
}

MdDialog 已关闭(),但始终发生以下检测更改错误:

The MdDialog is closed(), but a detection change error always occurs with the following:

ERROR Error: ViewDestroyedError: Attempt to use a destroyed view: detectChanges
    at viewDestroyedError (core.es5.js:8636)
    at Object.debugUpdateDirectives [as updateDirectives] (core.es5.js:12781)
    at checkAndUpdateView (core.es5.js:12122)
    at callWithDebugContext (core.es5.js:13184)
    at Object.debugCheckAndUpdateView [as checkAndUpdateView] (core.es5.js:12724)
    at ViewRef_.detectChanges (core.es5.js:10196)
    at asterisk.component.ts:37
    at ZoneDelegate.webpackJsonp.1467.ZoneDelegate.invokeTask (zone.js:414)
    at Object.onInvokeTask (core.es5.js:4119)
    at ZoneDelegate.webpackJsonp.1467.ZoneDelegate.invokeTask (zone.js:413)
View_MdDialogContainer_Host_0 @ MdDialogContainer_Host.html:1
proxyClass @ compiler.es5.js:14091
DebugContext_.logError @ core.es5.js:13124
ErrorHandler.handleError @ core.es5.js:1144
next @ core.es5.js:4757
schedulerFn @ core.es5.js:3830
SafeSubscriber.__tryOrUnsub @ Subscriber.js:236
SafeSubscriber.next @ Subscriber.js:185
Subscriber._next @ Subscriber.js:125
Subscriber.next @ Subscriber.js:89
Subject.next @ Subject.js:55
EventEmitter.emit @ core.es5.js:3816
NgZone.triggerError @ core.es5.js:4188
onHandleError @ core.es5.js:4149
webpackJsonp.1467.ZoneDelegate.handleError @ zone.js:385
webpackJsonp.1467.Zone.runTask @ zone.js:184
ZoneTask.invoke @ zone.js:476
timer @ zone.js:1491
setInterval (async)
scheduleTask @ zone.js:1501
webpackJsonp.1467.ZoneDelegate.scheduleTask @ zone.js:400
onScheduleTask @ zone.js:290
webpackJsonp.1467.ZoneDelegate.scheduleTask @ zone.js:394
webpackJsonp.1467.Zone.scheduleTask @ zone.js:225
webpackJsonp.1467.Zone.scheduleMacroTask @ zone.js:248
(anonymous) @ zone.js:1527
proto.(anonymous function) @ zone.js:1402
AsteriskComponent @ asterisk.component.ts:37
createClass @ core.es5.js:10870
createDirectiveInstance @ core.es5.js:10701
createViewNodes @ core.es5.js:12064
callViewAction @ core.es5.js:12508
execComponentViewsAction @ core.es5.js:12417
createViewNodes @ core.es5.js:12091
createRootView @ core.es5.js:11969
callWithDebugContext @ core.es5.js:13184
debugCreateRootView @ core.es5.js:12644
ComponentFactory_.create @ core.es5.js:9890
ComponentFactoryBoundToModule.create @ core.es5.js:3427
ViewContainerRef_.createComponent @ core.es5.js:10092
PortalHostDirective.attachComponentPortal @ material.es5.js:2135
MdDialogContainer.attachComponentPortal @ material.es5.js:19218
MdDialog._attachDialogContent @ material.es5.js:19486
MdDialog.open @ material.es5.js:19400
webpackJsonp.751.SideNavsComponent.openDialog @ side-navs.component.ts:39
webpackJsonp.751.SideNavsComponent.signIn @ side-navs.component.ts:35
(anonymous) @ SideNavsComponent.html:32
handleEvent @ core.es5.js:11892
callWithDebugContext @ core.es5.js:13184
debugHandleEvent @ core.es5.js:12772
dispatchEvent @ core.es5.js:8792
(anonymous) @ core.es5.js:10720
schedulerFn @ core.es5.js:3842
SafeSubscriber.__tryOrUnsub @ Subscriber.js:236
SafeSubscriber.next @ Subscriber.js:185
Subscriber._next @ Subscriber.js:125
Subscriber.next @ Subscriber.js:89
Subject.next @ Subject.js:55
EventEmitter.emit @ core.es5.js:3816
ToggleButton.toggle @ togglebutton.js:42
(anonymous) @ ToggleButton.html:4
handleEvent @ core.es5.js:11892
callWithDebugContext @ core.es5.js:13184
debugHandleEvent @ core.es5.js:12772
dispatchEvent @ core.es5.js:8792
(anonymous) @ core.es5.js:9384
(anonymous) @ platform-browser.es5.js:2683
webpackJsonp.1467.ZoneDelegate.invokeTask @ zone.js:414
onInvokeTask @ core.es5.js:4119
webpackJsonp.1467.ZoneDelegate.invokeTask @ zone.js:413
webpackJsonp.1467.Zone.runTask @ zone.js:181
ZoneTask.invoke @ zone.js:476
MdDialogContainer_Host.html:1 ERROR CONTEXT DebugContext_ {view: {…}, nodeIndex: 0, nodeDef: {…}, elDef: {…}, elView: {…}}

如何防止组件销毁后的 changeDetection 触发;换句话说,我怎样才能使这段代码正常工作而不会出现错误?

How can I prevent the changeDetection firing after the component is destroyed; in otherwords how can I make this code work without the error?

注意:尝试了很多关于 stackoverflow 的建议,但没有一个奏效.

NB: Tried many suggestions on stackoverflow but none worked.

谢谢

推荐答案

问题是对话框的关闭操作是从视图中删除项目,而您的 EventDispatcher IS NOT AN ANGULAR METHOD 所以它在区域上下文之外触发并吓坏了它.它是这样的:

The issue is the close action of the dialog is removing the item from the view, and your EventDispatcher IS NOT AN ANGULAR METHOD so it fires outside the zone context and freaks it out. It goes like this:

  • 视图中存在对话框,设置状态
  • 点击关闭
  • 触发您的活动开始
  • 您的活动已被读取(断章取义)
  • 从视图中删除(仍然脱离上下文)
  • 变更检测终于赶上了寻找组件中的变化,哦,组件在哪里?

您可以使用不同的方法与对话框进行通信,也可以切换到 onPush() 用于变化检测

You can either use a different method to communicate with the dialog, or switch to onPush() for change detection

我建议你改用 afterClosed 句柄:

I suggest you Use the afterClosed handle instead:

this. authEmailDialogRef.afterClosed().subscribe(result => {
  console.log(`Dialog result: ${result}`); // Pizza!
});

我直接从文档中提取了该片段:HERE

I pulled that snippet straight from the docs: HERE

这篇关于ViewDestroyedError:尝试使用被破坏的视图:detectChanges的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆