Shadow DOM 解决样式与 DOM 隔离问题:防止外部样式污染、阻止外部 JS 篡改内部结构,并为 Web Components 提供封装基础;需显式调用 attachShadow() 创建,仅现代浏览器支持,不隔离 JavaScript 作用域。

HTML5 的 Shadow DOM 是浏览器原生支持的组件封装机制,它让自定义元素能拥有独立的 DOM 树、样式作用域和事件边界;HTML4 完全没有等价能力,所谓“封装”只能靠 JS 模拟或约定俗成的命名/结构,既不隔离也不可靠。
Shadow DOM 解决什么问题
核心是「样式与 DOM 隔离」:外部 CSS 不会意外影响组件内部,组件内部样式也不会泄露出去,同时 querySelector、getElementById 等默认查不到 shadow 内部节点。
- 避免全局样式污染(比如一个
.button规则不会命中 shadow 内的) - 防止外部 JS 直接篡改组件结构(除非显式调用
shadowRoot) - 为 Web Components 提供封装基础,配合
customElements.define使用
怎么创建一个基本的 Shadow DOM
通过 attachShadow() 方法挂载,必须指定 { mode: 'open' } 或 { mode: 'closed' }。绝大多数场景用 open,否则连开发者工具都看不到 shadow 内容。
const el = document.querySelector('#my-widget');
const shadow = el.attachShadow({ mode: 'open' });
shadow.innerHTML = `
`;-
mode: 'closed'会让el.shadowRoot返回null,调试困难,一般不用 - 不能在 等任意元素上 attach —— 只有部分元素支持,如、
、等(但、不行),最好用自定义标签名(如)- shadow 内部的
是局部生效的,无需加 scoped 属性HTML4 有没有类似 Shadow DOM 的封装方式
没有。HTML4 时代不存在任何浏览器级的 DOM 封装能力。所谓“组件化”只能靠手工模拟:
立即学习“前端免费学习笔记(深入)”;
- 用
iframe实现强隔离——但开销大、通信麻烦、SEO 友好性差 - 靠 JS 构造函数 + 命名空间(如
MyWidget.init())+ 约定 class 前缀(如mywidget-button)——样式和 DOM 全部暴露,易冲突 - 用
document.createElement('div')手动拼 HTML 字符串再插入——无作用域、无生命周期、无样式隔离
这些都不是封装,只是组织代码的习惯。真正的封装需要浏览器内核支持,而那是 HTML5 中
Shadow DOM和Custom Elements规范带来的根本变化。容易被忽略的关键点
Shadow DOM 不是自动开启的,也不随元素创建而存在;它必须显式调用
attachShadow(),且只对现代浏览器有效(IE 完全不支持,Edge 18- 需前缀)。更重要的是:它只隔离 DOM 和样式,不自动处理 JavaScript 作用域——shadow 内的脚本仍运行在全局上下文中,变量依然可能冲突。 - shadow 内部的










