#angular #angular-directive
#угловой #угловая директива
Вопрос:
tree-view.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
- Уровень 2.1
Почему консоль печатает несколько раз. в чем мои ошибки
Ответ №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");
}
}
}
Комментарии:
1. Да, я привязываю несколько раз, используя рекурсивную функцию, так как я могу решить эту проблему.