You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular递归表格点击父行子行闪显问题求助

解决Angular递归表格子行显示后立即消失的问题

看起来你遇到的核心问题是原生DOM操作和Angular模板驱动渲染的冲突,再加上<a>标签的默认跳转行为没彻底阻止,导致子行刚显示就被重新渲染隐藏了。我给你一步步拆解修复方案:

1. 先堵上语法漏洞(你代码里的几个小错误)

先把你TypeScript代码里的语法问题修复,这些也可能导致组件异常:

// 修复后的TypeScript代码
sampletree() { 
  var ele = <HTMLTableElement>document.getElementById("tableid"); 
  ele.addEventListener("click", (ev: MouseEvent) => { 
    var element = ev.target as HTMLElement; 
    if (element.tagName !== "A") return false; 
    ev.preventDefault(); 
    var row = element.closest("tr"); 
    var cls = row.classList[0]; 
    var lvl = +(cls.slice(-1)) + 1; 
    cls = cls.slice(0, -1) + lvl; 
    while ((row = nextTr(row)) && (row.className.includes(cls) || row.className.includes("open"))) 
      row.classList.toggle("open"); 
  }); 

  function nextTr(row) { 
    while ((row = row.nextSibling) && row.nodeType != 1); 
    return row; 
  } 
} 

getTableParent1(): void { 
  this.service.getTableParent1()
    .subscribe(TableParent1 => this.TableParent1 = TableParent1); // 补全闭合符号
} 

getChild(event: Event): void { 
  event.preventDefault(); // 新增:阻止默认跳转
  event.stopPropagation(); // 新增:阻止事件冒泡
  this.service.getTablechild1()
    .subscribe(Tablechild1 => this.Tablechild1 = Tablechild1); // 修正变量名+补全闭合符号
} 

ngOnInit() { 
  this.getTableParent1(); // 修正方法名
  // this.sampletree(); 先注释掉,后面换成Angular的状态管理
}

2. 彻底阻止<a>标签的默认行为

你页面里的<a href="#">会触发页面跳转(回到顶部),这会触发Angular的变更检测甚至组件重新渲染,直接导致子行消失。修改HTML里的点击事件:

<!-- 父行的<a>标签修改 -->
<a href="#" (click)="getChild($event)">{{parent.isOpen ? '-' : '+'}}</a>

3. 用Angular状态管理替代原生DOM操作

原生的addEventListener和类切换很容易和Angular的模板渲染冲突,建议给每个父行维护一个isOpen状态,用*ngIf控制子行显示:

第一步:给父行数据添加状态属性

getTableParent1(): void { 
  this.service.getTableParent1()
    .subscribe(tableParent1 => {
      // 给每个父项添加isOpen状态,默认关闭
      this.TableParent1 = tableParent1.map(item => ({...item, isOpen: false, childData: []}));
    }); 
} 

第二步:修改HTML模板,用状态控制子行

如果你的子数据是和父行一一对应的,建议把子数据绑定到对应的父项上,避免所有子行同时显示:

<table class="table table-bordered table-hover" id="tableid"> 
  <thead> 
    <tr> 
      <th>test1</th> 
      <th>test2</th> 
    </tr> 
  </thead> 
  <tbody> 
    <!-- 父行 -->
    <tr class="level0" *ngFor="let parent of TableParent1"> 
      <td>
        <a href="#" (click)="toggleChild(parent, $event)">
          {{parent.isOpen ? '-' : '+'}}
        </a>
        {{parent.test2}}
      </td> 
      <td>{{parent.test1}}</td> 
    </tr> 

    <!-- 子行:仅对应父行打开时显示 -->
    <ng-container *ngFor="let parent of TableParent1">
      <tr class="level1" *ngFor="let child of parent.childData" *ngIf="parent.isOpen"> 
        <td><a href="#" (click)="toggleGrandChild(child, $event)">+</a>{{child.test1}}</td> 
        <td>{{child.test2}}</td> 
      </tr>
    </ng-container>
  </tbody>
</table>

第三步:实现状态切换和子数据加载方法

toggleChild(parent: any, event: Event): void {
  event.preventDefault();
  event.stopPropagation();
  
  // 切换展开/收起状态
  parent.isOpen = !parent.isOpen;
  
  // 仅展开时加载子数据(避免重复请求)
  if (parent.isOpen && parent.childData.length === 0) {
    // 假设父行有唯一id,传给接口获取对应子数据
    this.service.getTablechild1(parent.id)
      .subscribe(childData => {
        parent.childData = childData;
      });
  }
}

// 子行的展开方法(如果需要递归)
toggleGrandChild(child: any, event: Event): void {
  event.preventDefault();
  event.stopPropagation();
  // 同理,可以给子项添加isOpen状态,加载更深层级的数据
}

4. 简化CSS,交给Angular控制显示

移除原来原生DOM依赖的CSS规则,让*ngIf全权负责显示逻辑:

/* 保留基础样式 */
tr td { padding: 0.2em 0.4em; }
tr td:first-of-type { position: relative; padding: 0.2em 1em; }
tr td a { color: #0e879a; text-decoration: inherit; position: relative; left: -0.73em; font-size: 19px; }
tr.level1 td:first-of-type { padding-left: 1.5em; }
tr.level2 td:first-of-type { padding-left: 2em; }

/* 移除原生display控制,交给*ngIf处理 */
tbody>tr { display: table-row; }

核心思路总结

避免混合原生DOM操作和Angular的模板渲染——Angular的变更检测会自动管理DOM,原生操作很容易打破这种平衡。用组件内部的状态(比如isOpen)来控制子行的显示/隐藏,同时彻底阻止<a>标签的默认跳转行为,就能解决子行显示后立即消失的问题了。

内容的提问来源于stack exchange,提问作者njeoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:05:26