【问题标题】:Angular exception : attempt to use a dehydrated detector角度异常:尝试使用脱水检测器
【发布时间】:2016-04-04 14:00:01
【问题描述】:

查看了几个讨论此错误的主题后,我找不到任何理由让我的代码产生EXCEPTION: Attempt to use a dehydrated detector: PortsInputComponent_1 -> valueChange。我不认为堆栈跟踪有用,因为它只是角度代码,而不是我的。

我看过这些帖子:Angular2 EXCEPTION: Attempt to detect changes on a dehydrated detectorEXCEPTION: Attempt to detect changes on a dehydrated detectorWhat is a dehydrated detector and how am I using one here?,以及在这个 github 问题上https://github.com/angular/angular/issues/6786

他们似乎都在使用一些异步操作,而我没有,而且这些解决方案都不适合我的项目。请不要将其作为重复项关闭。

基本上我想要做的是多个端口的特殊输入。我希望始终有一个空白输入,因此用户不必按下按钮即可添加新输入。我不想有多个空白输入,所以当用户删除最后一个字符时我需要删除它们。下面的演示完美地做到了这一点。

这是 plunker 内的代码:

import { Component, Input }             from 'angular2/core';

@Component({
  selector: 'my-ports-input',
  template:`
<div layout-gt-sm="row" layout-wrap>

  <md-input-container class="md-block" flex-gt-sm
      *ngFor="#port of values() ; #i = index ;">
    <label>Port</label>
    <input md-input class="ports-input" type="text" size="6"
        [value]="port.title" (input)="changeValueAtIndex(i, $event)" />
  </md-input-container>
</div>
`
})

export class PortsInputComponent {
  // More complex model that contains an array of string values
  @Input() attribute: {value : string[]}
  strings = []

  changeValueAtIndex(index, event) {
    // Case where we changed the value of the latest port : we add a new input
    if (!this.attribute.value[index]) {
      this.strings.push({ title: '' })
    }

    this.attribute.value[index] = event.target.value

    if (event.target.value.length === 0) {
      this.attribute.value.splice(index, 1)
      this.strings = [] // Should reload the array, but also causes the issue below
    }
  }

  // Use this function that returns an array of objects instead of an array of string.
  // Using directly attribute.value (array of string) cause this error:
  // https://github.com/angular/angular/issues/6786
  //
  // Returning directly this.attribute.value.map((value) => { return {title: value} })
  // causes an infinite loop of error... for some reason
  // So use an intermediate variable instead
  values() {
    if (!this.strings.length) {
      let values: string[] = this.attribute.value
      this.strings = values.map((value) => { return {title: value} })
      this.strings.push({ title: '' })
    }
    return this.strings
    // return this.attribute.value.map((value) => { return {title: value} })
  }
}

有谁知道为什么在我的情况下会引发此错误?

我想在a plunker 中重现此错误,但不幸的是它不会导致任何异常,我在我的应用程序和 plunker 之间看到的唯一区别是attribute 变量。在我的应用程序中,它是一个模型而不是 JSON 对象,它可以改变一些东西吗?

【问题讨论】:

  • Plunker 示例使用beta.8 运行,因此它应该是可重现的。 AFAIR 它与组件在被移除之后或移除时触发事件有关。
  • 确实,我查看了 README.md 文件,该文件声明 beta 0,即使它在索引中加载 beta 8。这也是我从 github issue 中了解到的,但无法弄清楚为什么会在我的情况下发生。
  • 自述文件刚刚过时。
  • 有没有办法找到我的代码的哪一部分导致了这个错误?
  • 我认为它与src/ports-input.component.html中动态生成的输入的事件绑定有关

标签: angular


【解决方案1】:

稍微延迟此代码可能会解决(未测试,因为我无法重现)

  changeValueAtIndex(index, event) {
    setTimeout(() => {
      // Case where we changed the value of the latest port : we add a new input
      if (!this.attribute.value[index]) {
        this.strings.push({ title: '' })
      }

      this.attribute.value[index] = event.target.value

      if (event.target.value.length === 0) {
        this.attribute.value.splice(index, 1)
        this.strings = [] // Should reload the array, but also causes the issue below
      }
    },0});
  }

【讨论】:

  • this.strings = [] 周围的 setTimeOut 为 1ms(0 无效)消除了错误,谢谢。虽然你能解释一下为什么延迟这个 1ms 的代码会阻止一个事件从一个被移除的组件中触发吗?
  • 有些事情会在 Angular 仍在处理之前的更改时推动更改。 setTimeout 只是改变处理事物的顺序。 Angular 可以完成它的工作,并且只有在 Angular 再次处于稳定状态后才会执行此代码。当问题在 Angular 中得到解决时,它应该在内部注意不要超出预期的顺序执行。
猜你喜欢
  • 2016-06-27
  • 1970-01-01
  • 1970-01-01
  • 2021-09-28
  • 2017-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多