【问题标题】:Angular Directive call multiple timesAngular 指令多次调用
【发布时间】:2020-10-14 04:16:19
【问题描述】:

树视图.html

<div *ngFor="let item of nodes; let i=index" class="parent" [id]="item.name" appTreeView>
        {{item.name}}
        <div class="child" *ngIf="item.child">
            <app-tree-view [nodes]="item.child"></app-tree-view>  // recursive call 
        </div>
</div>

treeview.ts

this.data=[
      {
        name:"level 1",
        child:[
          {
            name:"level 1.1",
          }
        ]
      },
      {
        name:"level 2",
        child:[
          {
            name:"level 2.1",
            child:[
              {
                name:"level 2.1.1"
              }
            ]
          }
        ]
      }
    ]

directive.ts

import { Directive, HostListener,Renderer2 } from '@angular/core';

@Directive({
  selector: '[appTreeView]',
})
export class TreeViewDirective {

  constructor(private render:Renderer2) { }
  @HostListener('click',['$event'])
  check(event){
    console.log(event.target.id);
    const avalclass:string=event.target.classList.value;
    if(avalclass.includes('expand')){
      this.render.removeClass(event.target,'expand');
    }else{
      this.render.addClass(event.target,'expand');
    }
    
  }
}

输出

  • 1 级
  • 2 级

如果我点击 2 级展开子菜单 2.1 级 控制台打印一次

  • 1 级
  • 2 级
    • 2.1 级

然后我点击 2.1 级展开子菜单 2.1.1 控制台打印两次

  • 1 级
  • 2 级
    • 2.1级
      • 2.1.1 级

为什么控制台打印多次。我的错误是什么

【问题讨论】:

    标签: angular angular-directive


    【解决方案1】:

    由于您正在使用递归调用父母及其后代,控制台多次打印相同的内容。 您将多次绑定单击事件,具体取决于您单击的元素所在的级别。如果您知道代码的流程:

    • 如果您单击第一级项目(1 级或 2 级):它会打印一次。
    • 如果您单击第二级项目(1.1 级或 2.2 级):它会打印两次,一次用于第二级,另一次用于第一级。
    • 等等..

    我已经准备了一个演示,其中包含您在问题中输入的代码。您可以在控制台中看到谁在调用事件以及谁是每次的宿主元素。

    https://stackblitz.com/edit/angular-recursion-directives?file=src/app/tree-view.directive.ts

    您可以解决在指令中添加标志并在检查函数中检查它的问题:

    if (this.isFired) {
          return;
        }
    this.isFired = true;
    

    或者比较当前宿主元素和触发事件的元素:

    if(this.el.nativeElement.id == event.target.id){
       console.log("click on: " + event.target.id);
          const avalclass: string = event.target.classList.value;
    
          if (avalclass.includes("expand")) {
            this.render.removeClass(event.target, "expand");
          } else {
            this.render.addClass(event.target, "expand");
          }
        }
    }
    

    【讨论】:

    • 是的,我正在使用递归函数多次绑定,所以我该如何解决这个问题。
    猜你喜欢
    • 2015-01-02
    • 2015-08-17
    • 2023-04-03
    • 2014-12-24
    • 1970-01-01
    • 2016-06-24
    • 1970-01-01
    • 2019-04-29
    • 1970-01-01
    相关资源
    最近更新 更多