Angular - 链接到 ViewChild 的函数执行两次

Angular - Function linked to ViewChild executing twice

我有三个组件,Nav、App、Form。在 Nav 组件中,我有一个函数可以更改 CSS 的位置,我可以从 Nav 和 App 组件(从 Form 组件获取触发器)调用此函数。我的问题是,当我从 NAV 组件调用函数时,它会触发两次。

我尝试删除 @ViewChild 并解决了问题,但无法按我想要的方式工作。我环顾四周,发现我应该使用 stopPropagation,但所有示例都有 event.StopPropgation,我不明白如何将其应用于我的函数。

Html 用于导航

    <div class="navButton add" (click)="addFormToggle()">
      <div class="bar vertical"></div>
      <div class="bar horizontal"></div>
    </div>

用于导航的 TS

When the button is clicked, it's function fires the CSS change function and another function to render the form Component.

import { Component, OnInit, Renderer2, ElementRef, Output, EventEmitter, ChangeDetectorRef } from '@angular/core';

@Component({
  selector: 'menu-navigation',
  templateUrl: './menu-navigation.component.html',
  styleUrls: ['./menu-navigation.component.scss']
})
export class MenuNavigationComponent implements OnInit {

  constructor(private renderer: Renderer2, private el: ElementRef, private ref: ChangeDetectorRef) { }
  ngOnInit() { }

  @Output() addFormToggleEvent = new EventEmitter<Event>();

  addToggle;

  addFormIconToggle() {
    this.addToggle = !this.addToggle;

    let vert = document.getElementsByClassName("vertical");
    let horz = document.getElementsByClassName("horizontal");

    if (this.addToggle) {
      this.renderer.addClass(vert[0], "verticalToggle");
      this.renderer.addClass(horz[0], "horizontalToggle");
    }
    else if (!this.addToggle) {
      this.renderer.removeClass(vert[0], "verticalToggle");
      this.renderer.removeClass(horz[0], "horizontalToggle");
    }

  }

  addFormToggle() {
    this.addFormToggleEvent.emit();
    this.addFormIconToggle();
  }
}

App.Component HTML

<div class="mainContainer">
    <div class="header">
        <menu-navigation (addFormToggleEvent)="childAddFormToggle()">
        </menu-navigation>
    </div>
    <div class="newProjectForm" *ngIf="toggleForm">
    <project-form (closeFormEvent)="childAddFormToggle()"></project-form>
    </div>
</div>

App.component TS

import { MenuNavigationComponent } from './menu-navigation/menu-navigation.component';

import { Component, Input, ViewChild } from '@angular/core';


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'journal';
  toggleForm;

  public toggleProjectForm: Event;

  @Input() event: Event;
  @ViewChild(MenuNavigationComponent, { static: false }) child: MenuNavigationComponent;

  constructor() { }

  childAddFormToggle() {
    this.toggleForm = !this.toggleForm;
    this.child.addFormIconToggle();
  }
}

它很可能触发两次,因为您调用了两次:一次是在您的 childAddFormToggle() 方法中,一次是在 addFormToggle().

中调度事件时

但是从您的代码中我什至看不到这样做的必要性。你可以像这样重写它:

Html 用于导航

<div class="navButton add" (click)="toggleFormToggle()">
  <!-- Add the class in HTML conditionally, angular will take care of applying the -->
  <!-- class for you when 'addToggle' is set to true and removing it when set to false -->

  <div class="bar vertical" [class.verticalToggle]="addToggle"></div>
  <div class="bar horizontal" [class.horizontalToggle]="addToggle"></div>
</div>

导航 TS

import { Component, OnInit, Input, Output, EventEmitter} from '@angular/core';

@Component({
  selector: 'menu-navigation',
  templateUrl: './menu-navigation.component.html',
  styleUrls: ['./menu-navigation.component.scss']
})
export class MenuNavigationComponent implements OnInit {

  // With this convention (@Input addToggle, @Output addToggleChange ) you can use two-way binding when using this component [(addToggle)]="someVariable"
  @Input() addToggle:boolean = false;
  @Output() addToggleChange = new EventEmitter<boolean>();

  constructor() { }
  ngOnInit() { }

  // Only set the value in the internal state and bubble up the event, angular handles the class setting for us in the template
  toggleFormToggle() {
    this.addToggle = !this.addToggle;
    this.addToggleChange.emit(this.addToggle);
  }
}

app.component html

<div class="mainContainer">
    <div class="header">
        <!-- Just two-way bind the variable toggleForm so it will effective mirror the addToggle variable in menu-navigation -->

        <menu-navigation [(addToggle)]="toggleForm">
        </menu-navigation>
    </div>
    <div class="newProjectForm" *ngIf="toggleForm">

    <!-- Change the variable, the two-way binding above will reflect it back into the menu-navigation component -->
    <project-form (closeFormEvent)="toggleForm = !toggleForm"></project-form>
    </div>
</div>

app.component ts

import { Component, Input, ViewChild } from '@angular/core';


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'journal';
  toggleForm:boolean = false;

  @Input() event: Event;

  constructor() { }

  // You don't actually need a method doing anything for you
}

这里是工作 Stackblitz 展示我的方法。