details 标签本身不卡,卡的是默认展开时内部大量 dom 全量解析与布局;真正懒加载需用 template + intersectionobserver 按需挂载内容,并同步维护 aria 属性保障可访问性。

details 标签本身不卡,卡的是你往 details 里塞了 5000 行表格、10 万字文本或嵌套组件后,还让它默认展开——浏览器照常构建全部 DOM、计算布局、触发重排,和普通 div 没区别。
details 默认展开时,内部 DOM 全量解析无法跳过
很多人误以为 details[open] 是“懒加载”,其实不是:只要 HTML 中写了 open 属性,或 JS 执行 el.open = true,内部所有子节点就会立即进入 DOM 树、参与样式计算和布局。哪怕内容是 <table><tbody>...5000 个 <tr></tr>
</tbody></table>,浏览器也得全量解析。
- 实测:一个含 2 万行
<tr> 的 <code><details open></details>,首次渲染耗时 >3.8 秒,主线程冻结,滚动/输入无响应 - 关键点:不是
details慢,是它没做任何 DOM 节流或虚拟化——它只是个语义容器,不自带性能逻辑 - 若用 JS 动态设
open = true,也一样;只有首次未挂载、且从未设过open,内部才真正“离线” - 把
details的真实内容移入<template id="details-content">...</template>,details体内只留占位提示(如 “点击加载数据”) - 用
IntersectionObserver监听details进入视口(可设rootMargin: '100px'提前触发) - 触发后,调用
template.content.cloneNode(true)插入details的<summary></summary>后,并设open = true - Safari 旧版兼容?降级用
getBoundingClientRect()+requestAnimationFrame轮询,但只检查当前滚动区域内的details,别遍历全部 <table style="table-layout: fixed"> 必须写在 <code>table标签上,不能靠 CSS 类;同时配<col width="120">,否则列宽计算仍会扫描全部<td> <li>表格行数 >200 就别用 <code>innerHTML = hugeString—— 即使内容已挂载,一次性插入仍会卡死。改用DocumentFragment分批(每 500 行一批),每批后加await new Promise(r => setTimeout(r, 0))让出主线程- 禁用
details上的will-change: transform:对表格内元素加这个声明,现代浏览器反而强制提升图层,增加内存开销,且对滚动无加速效果 - 如果表格支持排序/筛选,每次更新
tbody时,要清空旧节点再用 Fragment 重插,别用innerHTML +=或循环appendChild - 首次加载后,把已构建的
DocumentFragment缓存到details.dataset.fragment或 WeakMap 中,后续展开直接复用 - 收起时不要
removeChild,改用details.querySelector('.content').style.display = 'none'(前提是内容已用 class 包裹) - 若内容含交互元素(如按钮、input),缓存时需保留事件委托绑定点,别用内联
onclick;收起时不清事件,展开时也不重绑 - 注意:
details的toggle事件不区分是用户点击还是 JS 设置,监听时加event.target === details判断来源,避免自触发循环
用 template + IntersectionObserver 控制 details 内容的实际挂载时机
真正有效的懒加载,是让内容只在用户即将看到时才插入 DOM。不能靠 display: none 或 hidden,它们仍参与构建和样式计算。
details 内部有表格时,必须同步启用 table-layout: fixed + DocumentFragment 分批
一旦内容挂载,性能瓶颈立刻转移到内部结构。如果里面是个大数据表格,前面所有优化都白费。
details 嵌套过深或高频切换 open/close 时,避免重复构建
用户快速点击收起再展开,若每次都销毁再重建内容,既浪费又易丢状态(比如表格滚动位置、input 输入值)。
最易被忽略的一点:details 的语义价值在无障碍(a11y),但如果你用 template 延迟挂载,又没同步补全 aria-expanded 和 aria-controls,屏幕阅读器会完全丢失状态切换。性能优化不能以牺牲可访问性为代价。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











