必须写在自定义元素内,浏览器自动将其内容作为 open 模式 shadow root 渲染,不执行 JS、不加载资源;内置元素如 不支持,样式和 需写在 template 内,适用于 SSR 和静态 HTML 场景。

template 标签怎么配合 shadowroot 属性用?
直接在 上加 shadowroot 属性,是声明式 Shadow DOM 的核心用法。它不是“把 template 当作普通模板来克隆”,而是让浏览器原生识别:这个 的内容要立刻作为宿主元素的 shadow root 渲染,且不执行 JS、不加载资源(除非显式写入)。
常见错误是把它当 document.importNode() 的替代品 —— 实际上它绕过了 JS 初始化阶段,更适合 SSR 和静态 HTML 场景。
-
shadowroot必须写在标签上,不能写在宿主元素上 - 宿主元素必须是自定义元素(如
),不能是或等内置标签mode只支持"open";"closed"不被声明式语法支持- 浏览器会自动将
内容挂载为 shadow root,并清空宿主元素的 light DOM为什么不能在 div 上用 template + shadowroot?
因为规范明确限定:只有**自定义元素**(通过
customElements.define()注册过的)才能作为声明式 Shadow DOM 的宿主。这是硬性限制,不是兼容性问题。如果你写了:
hello
浏览器会完全忽略shadowroot属性,会作为普通子节点渲染在 light DOM 中。- 检查控制台不会报错,但
div.shadowRoot是null - 想快速验证是否生效?查宿主元素的
shadowRoot属性是否为ShadowRoot实例 - 若需对内置元素附加 Shadow DOM,只能用
attachShadow(),且部分内置元素(如、)根本不允许
声明式 Shadow DOM 的样式和 slot 怎么写?
写法和 JS 创建的 Shadow DOM 完全一致,但要注意解析时机:所有样式和
都在 HTML 解析阶段就位,不依赖 JS 执行。示例:
默认标题 默认内容 -
必须写在内部,外部不会进入 shadow DOM -
名称必须与宿主元素内对应内容的slot属性值匹配,否则 fallback 内容生效 - 不支持动态修改
内容 —— 浏览器解析完就固化了,后续改 innerHTML 无效
服务端渲染时 template + shadowroot 的实际价值在哪?
关键点在于:无需等待 JS 加载和执行,HTML 字符串一返回就能呈现封装好的组件结构和样式。这对首屏性能和 SEO 很重要。
但容易被忽略的是——如果组件需要响应式逻辑或事件绑定,你仍得在 JS 中补上:
customElements.define('my-card', class extends HTMLElement { connectedCallback() { this.shadowRoot.querySelector('button').onclick = () => { /* ... */ }; } });- 声明式只解决结构+样式的“静态封装”,行为逻辑仍需 JS 补全
- 若用 React/Vue 等框架,它们目前基本不生成声明式 Shadow DOM,得手动桥接
- CDN 或静态站点生成器(如 Astro、Hugo)可直接输出带
shadowroot的 HTML,零 JS 即可渲染隔离视图
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











