事件从Angular2组件触发两次

时间:2017-09-15 17:17:25

标签: javascript angular

我在使用两次触发的setter方法时遇到问题。我的子组件有一个表单,其中videoId的设置值也会设置frame的值。

还有一个输入允许您设置frame

的值

当我通过html输入在子组件中设置videoId时,子组件中frame的setter会触发两次。我添加了一些逻辑来检查某些值以防止事件发射器(this.frameChange.emit(frame))触发两次,因为这会在父组件中进行API调用。这只是一个绑带,我已经达到了它的局限。

如果我在子组件的frame setter中放置断点,则调用堆栈会在第一次触发时显示以下内容...

=> set                                   frame.controls.component.ts:52
   FrameControlsComponent.onSubmit          frame.controls.component.ts:52`
   View_FrameControlsComponent0.handleEvent_0   /SuperApp...factory.js:546
   ...

和第二次射击......

=> set                                   frame.controls.component.ts:52
Wrapper_FrameControlsComponent.check_frame (/SuperAppModule/FrameControlsComponent/wrapper.ngfactory.js:31)
View_SuperAppComponent0.detectChangesInternal (/SuperAppModule/SuperAppComponent/component.ngfactory.js:393)
AppView.detectChanges (view.js:438)
DebugAppView.detectChanges (view.js:633)
AppView.internalDetectChanges (view.js:423)
View_SuperAppComponent_Host0.detectChangesInternal (/SuperAppModule/SuperAppComponent/host.ngfactory.js:30)
AppView.detectChanges (view.js:438)
DebugAppView.detectChanges (view.js:633)
ViewContainer.detectChangesInNestedViews (view_container.js:71)
View_Pages0.detectChangesInternal (/PagesModule/Pages/component.ngfactory.js:98)
AppView.detectChanges (view.js:438)
DebugAppView.detectChanges (view.js:633)
AppView.internalDetectChanges (view.js:423)
View_Pages_Host0.detectChangesInternal 
...

(堆叠痕迹还有更多,请告诉我是否过早切断它们。)

我已经采取的处理这个问题的逻辑是不可持续的,我真的需要找到为什么这些事件发生两次的根源。我理解第一个电话的来源,但不是来自Wrapper_FrameControlsComponent.check_frame

的第二个来电

以下是相关代码

<!-- PARENT HTML -->
<div class="card w-100 card-panel">
  ...
  <frame-controls [(videoId)]="videoId"  [(frame)]="frame"></frame-controls>
  ...
</div>

------

<!-- CHILD HTML -->
<input class="form-control" type="number" step="1" placeholder="ID"
           id="videoId" name="videoId" #videoId="ngModel"
           [ngModel]="model.videoId" (ngModelChange)="setVideoId($event)">

<input type="number" step="1" class="form-control" placeholder="Number"
                 id="frame" name="frame" #frame="ngModel"
                 [(ngModel)]="model.frame">

...

// PARENT COMPONENT

@Component({
  selector: 'super-app',
  ...
  host: {
    '(window:keydown)': 'handleKeyDown($event)',
    '(window:keyup)': 'handleKeyUp($event)'
  }
})
export class SuperAppComponent implements AfterViewInit {
  @ViewChild('container') private elContainer: ElementRef;

  private _frame: number;
  get frame(): number {
    return this._frame;
  }

  set frame(frame: number) {
    this._frame = frame;
  }

  constructor(@Inject(DOCUMENT) private document: HTMLDocument, ...) {
    ...
  }
  ...
}


// CHILD COMPONENT

@Component({
  selector: 'frame-controls',
  ...
})
export class FrameControlsComponent implements AfterViewInit {
  @Output() frameChange = new EventEmitter<number>();

  public model = {
    videoId: undefined,
    frame: undefined,
  };

  private _videoId: number;
  @Input()
  get videoId(): number {
    return this._videoId;
  }

  set videoId(videoId: number) {
    if (!_.isUndefined(videoId) && (videoId !== this._videoId)) {
      this._videoId = videoId;
      this.model.videoId = videoId;
      this.videoIdChange.emit(videoId);
      ...
    }
  }

  private _frame: number;
  @Input()
  get frame(): number {
    return this._frame;
  }

  set frame(frame: number) {
    if ( !_.isUndefined(frame) && this._frame != frame ) {  // TODO WHY DOES THIS FIRE TWICE THIS LOGIC IS HACKY AND DOES NOT WORK FOR ALL SCENARIOS
      this._frame = frame;
      this.model.frame = frame + 1;
      this.frameChange.emit(frame);
    }
  }

  constructor(...) {
  }

  public onSubmit() {
    if (this.videoId !== this.model.videoId) {
      this.videoId = this.model.videoId;
    }
    if (this.frame !== this.model.frame) {
      this.frame = this.model.frame - 1;
    }
  }

  public setVideoId(videoId: number) {
    this.model.videoId = videoId;
    this.model.frame = 1;
  }

  public setFrame(frame: number) {
    frame = _.clamp(frame, 1, this.maxFrames);
    this.frame = frame - 1;
  }
}

0 个答案:

没有答案