用 console.log 配合 %o 占位符和自定义 #debug-panel 容器实现可折叠调试面板,通过 mutationobserver 监听 dom 变化并节流更新,仅在 data-debug 属性存在时启用,避免生产环境泄漏。

用 console.log 配合 CSS 实现可折叠调试面板
浏览器控制台日志太散,想集中看 HTML 结构变化?别写独立弹窗,直接在页面里塞个轻量调试面板就行。
核心思路是:用 console.log 输出结构化对象时,配合 %o 或 %O 占位符,再用 CSS 控制其容器的显示/折叠。但注意——console.log 本身不渲染 DOM,所以得自己造一个 <div id="debug-panel"> 容器,再用 JS 往里追加内容。
<ul>
<li>每次更新前先清空 <code>innerHTML,避免日志无限叠加
style="max-height: 300px; overflow-y: auto; font-family: monospace; font-size: 12px;",防止撑爆页面JSON.stringify(obj, null, 2) 格式化对象,比直接插 obj 更易读;但注意循环引用会报错,得加个简易 replacer 过滤监听 DOM 变化并自动更新面板内容
想让面板实时反映某个区域的结构变化?不能靠定时轮询,要用 MutationObserver。
它比 DOMSubtreeModified 事件性能好得多,也比监听 innerHTML 更可靠(后者对属性变更、文本节点修改无效)。
- 观察目标设为需要监控的父容器,如
document.querySelector('#app') -
childList: true捕获增删子节点,subtree: true进入深层,attributes: true抓属性变动 - 回调里别直接调
console.log,而是更新面板的textContent或重新生成pre块,避免重复打印 - 注意:频繁触发时要做节流,比如用
setTimeout延迟 100ms 后统一刷新一次面板
用 data-debug 属性标记开发专用结构
生产环境要彻底隐藏调试信息?靠 JS 判断 location.hostname 不够稳,容易漏掉本地 file:// 场景。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
更稳妥的做法是:只在带 data-debug 属性的元素上启用日志输出和面板更新,上线前全局删掉该属性即可,不用改逻辑代码。
- 初始化时检查
document.body.hasAttribute('data-debug'),没有就直接 return - 面板容器也加上
data-debug,CSS 里写[data-debug] #debug-panel { display: block; },没属性就默认display: none - 这样连样式、JS、HTML 全部开关一致,不会出现“JS 关了但面板还挂着”的尴尬
避免把 console.table 当万能结构查看器
console.table 看数组或键值对确实清爽,但它对嵌套对象、DOM 节点、函数完全不友好——会显示成 [object Object] 或 function () {},失去结构信息。
尤其当你要查一个组件的 props 或 state 时,console.table 基本失效。
- 遇到对象嵌套超过 2 层,改用
console.log('%o', obj),点击控制台里的三角箭头可展开 - 想在面板里展示类似效果?用
JSON.stringify(obj, (key, val) => typeof val === 'function' ? '[Function]' : val, 2)做安全序列化 - DOM 元素别直接
console.log(el),改用el.outerHTML或el.cloneNode(true).outerHTML(避免污染原节点)
最麻烦的其实是异步时机:比如 Vue 的 nextTick 或 React 的 useEffect 之后才真正渲染完成,这时候再抓 DOM 才准。漏掉这一步,面板里永远显示旧结构。










