Shadow DOM 配合 <slot> 实现灵活头部布局,关键在于将“头部”定义为可替换的内容区域而非写死内容;必须通过自定义元素+Shadow DOM启用slot,外部内容需为直系子节点且name匹配,支持fallback、多级组合及::slotted/CSS变量样式控制。

Shadow DOM 配合 <slot> 实现灵活头部布局,关键在于把“头部”定义为可替换的内容区域,而不是写死在组件内部。它不是靠 CSS 定位或 div 嵌套模拟,而是通过原生内容分发机制,让使用者决定头部里放什么——标题、图标、操作按钮、搜索框,甚至整个导航栏。
必须用自定义元素 + Shadow DOM 才能启用 slot
直接在普通 HTML 里写 <slot name="header"></slot> 是无效的。浏览器会忽略它,不报错也不渲染。要让它工作,得走标准 Web Components 流程:
- 定义一个合法自定义标签,比如
<my-card>或<app-header-layout>,名字必须含短横线 - 在类的
constructor或connectedCallback中调用this.attachShadow({ mode: 'open' }) - 把带
<slot name="header">的结构写进 shadowRoot,例如:<header class="layout-header"><slot name="header">默认标题</slot></header>
外部使用时,内容必须是直系子节点且 name 匹配
头部内容不会自动“穿透”多层结构。它只认紧贴在自定义标签内部的第一层元素:
- ✅ 正确:
<my-card><h1 slot="header">用户中心</h1></my-card> - ❌ 错误:
<my-card><div><h1 slot="header">用户中心</h1></div></my-card>(<h1>是孙节点,被跳过) - ⚠️ 注意大小写:
<slot name="Header">不匹配<h1 slot="header">
支持 fallback 和多级组合,但需手动分发
插槽本身可以自带默认内容,比如 <slot name="header">页面标题</slot>,没传内容时就显示它。如果想实现“头部里再嵌套一个可定制的 logo 插槽”,不能靠嵌套 <slot> 标签——HTML 不允许那样做。正确做法是:
- 在父组件的 Shadow DOM 中预留
<slot name="header"> - 让用户传入的是一个已封装好的子组件,比如
<header-logo slot="header"></header-logo> - 而
<header-logo>自己也挂了 Shadow DOM,并在其内部定义<slot name="icon">和<slot name="text">
样式控制:用 ::slotted 和 CSS 变量保持灵活性
头部内容来自外部,但样式需要统一协调。这时不能靠外部全局 CSS 直接覆盖,而要用 Shadow DOM 提供的安全方式:
-
::slotted(h1)可以给所有塞进 header 插槽的<h1>加样式,但注意它只作用于直接子元素,不支持::slotted(div h1) - 用 CSS 自定义属性(变量)对外暴露控制点,比如在 shadowRoot 内写:
h1 { color: var(--header-color, #222); },外部通过my-card { --header-color: #007bff; }调整 - 如需更精细控制某一部分(如关闭按钮),可用
::part(close-btn)暴露接口,再由外部用my-card::part(close-btn) { ... }定制


















