直接嵌套tr导致浏览器强制修正DOM结构,破坏父子关系;须用data-level和data-parent-id显式标记层级,JS按父ID精准查询子行并控制显隐,图标旋转与状态严格同步,避免data属性迁移遗漏引发静默失效。

生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
为什么直接嵌套 <tr> 实现折叠会崩
<p>浏览器解析时强制修正非法结构:<code><tr> 只能是 <code><tbody>、<code><thead> 或 <code><table> 的直接子元素。写成父子 <code><tr> 嵌套,DOM 里第二个 <code><tr> 会被自动提升到同级 <code><tbody> 下,父子关系彻底丢失。JS 查 <code>nextElementSibling 拿不到子行,折叠后常留空行,colspan 错位导致边框塌陷。
必须用显式标记替代 DOM 位置依赖:
- 给每行加
data-level="1"、data-level="2"等明确层级 - 子行额外带
data-parent-id="101"(对应父行data-id="101") - 子行统一包裹在独立
<tbody> 或 <code><div role="rowgroup"> 中,避免被重排 <h3>怎么用 <code>data-level+ JS 精准控制三级展开三级不是“点一次全开”,而是逐级响应:点 level-1 行只展开其下所有 level-2 子行;再点某 level-2 行,才展开它的 level-3 子行。
关键在过滤范围,不是全量操作:
立即学习“前端免费学习笔记(深入)”;
- 初始 HTML 中,每行必须有唯一
data-id和明确data-level - JS 查询用
document.querySelectorAll('tr[data-level="2"][data-parent-id="101"]'),而非tr[data-level="2"] - 切换显隐只改
style.display = 'none'或'table-row',不操作 class —— 防止.folded tr这类选择器误匹配深层子行 - 初始状态建议全显,JS 控制逻辑;别提前写
style="display:none",否则动态增删行时易出错
箭头图标旋转和状态怎么严格同步
图标方向必须和行显隐状态完全一致,否则用户点击无反馈感。纯 CSS
transform: rotate()最轻量,但必须绑定到触发元素本身,不能靠父容器统一控制。实操要点:
- 点击目标是
<span class="toggle-icon"></span>,不是整行<tr> <li>JS 中先查该 <code>span是否含expandedclass:el.classList.contains('expanded') - 收起时移除
expanded并设transform: rotate(0deg);展开时添加并设rotate(90deg) - 不要用
visibility: hidden控制显隐——它仍占布局空间,会导致点击区域偏移或滚动条异常 - 所有旧
data-属性是否已按新命名映射更新 - JS 查询是否从
document.querySelector('div[data-role="row"]')同步改为document.querySelector('tr[data-role="row"]') - 在 Chrome DevTools Elements 面板右键任意容器 → “Break on” → “Attribute modifications”,确认 class 或 data 属性变更没意外触发旧 JS 的 DOM 监听逻辑
重构后最常被忽略的断裂点
样式和 JS 不报错,但功能静默失效。最容易漏的是
data-属性迁移不完整。例如原结构:
<tr class="product-row" data-id="123">,你改成:<code><tr class="product-row" data-product-id="123">,但 JS 里还写着 <code>el.getAttribute('data-id')—— 返回null,后续逻辑全断,却没有任何报错提示。验证时务必检查:
- 初始 HTML 中,每行必须有唯一


















