slot是Web Components中唯一原生的内容分发机制,仅在Shadow DOM下生效,需调用attachShadow()、确保内容为直系子元素、严格匹配slot属性与name值,并正确使用::slotted()和slotchange事件。

slot 是 Web Components 中唯一原生支持的内容分发机制,不是语法糖,也不是框架特性——它由浏览器直接实现,且只在 Shadow DOM 环境下生效。没用 attachShadow(),slot 就不会工作;写了 slot 但没配对的 slot 属性或默认接收点,内容就会被丢弃。
为什么 slot 不渲染、内容“消失”了?
这是最常卡住新手的问题:写了 <slot name="header"></slot>,外部也写了 <h2 slot="header">标题</h2>,但页面上啥也没显示。
- 检查是否调用了
this.attachShadow({ mode: 'open' })—— 没挂 Shadow Root,slot根本不参与任何分发逻辑 - 确认外部元素是自定义元素的直系子元素:
<my-card><div><h2 slot="header">标题</h2></div></my-card>中的<h2>不会被识别,因为被<div>隔了一层 -
slot元素必须出现在 Shadow DOM 内部模板中,不能写在 Light DOM 里(比如写在<my-card>标签内部) - 如果用了
{ mode: 'closed' },虽然渲染不受影响,但 JS 无法通过shadowRoot.querySelector('slot')获取节点,调试时会误判为“没生效”
具名 slot 和默认 slot 的匹配规则很严格
匹配不是靠“名字相似”,而是精确的字符串比对 + 顺序约束:
-
<h3 slot="title">只匹配<slot name="title">,name="Title"或name="title-text"都不匹配 - 没有
slot属性的元素(如<p>正文</p>),只会尝试塞进第一个无name属性的<slot>;后面还有几个空<slot>,也不会继续分发 - 多个同名
<slot name="item">时,Light DOM 中所有slot="item"元素会按顺序依次填入每个 slot(每个 slot 收到一份副本),不是“广播式”复制 - 未被任何
<slot>匹配的节点,保留在 Light DOM 中,但完全不参与渲染(不是隐藏,是跳过)
::slotted() 样式只能作用于直接子元素
想给投射进来的 <h2> 加样式?别用 h2 { color: red; },那会污染全局;也别指望 .card ::slotted(h2 span) 能生效——::slotted() 不支持后代选择器。
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- 正确写法:
::slotted(h2)、::slotted([slot="footer"])、::slotted(.btn) - 错误写法:
::slotted(div h2)、::slotted(h2 > span)、::slotted(*)(通配符无效) -
::slotted()仅在 Shadow DOM 样式表中有效,且只捕获“被投射进来”的节点,不包括 slot 自身或 fallback 内容 - 若需更细粒度控制,得让传入内容自带 class,或在组件内用
assignedNodes()手动遍历处理
监听 slotchange 事件要注意时机和范围
slotchange 不是“一劳永逸”的响应机制,它只在内容动态变更时触发,而且绑定位置非常关键。
立即学习“前端免费学习笔记(深入)”;
- 必须直接绑定在目标
<slot>上:shadowRoot.querySelector('slot[name="header"]').addEventListener('slotchange', handler);绑在父容器或shadowRoot上无效 - 首次渲染完成时不会触发该事件,哪怕 Light DOM 已有内容 —— 它只响应后续的
appendChild、removeChild等 DOM 变更 - 事件不冒泡,也不捕获,无法委托;多个 slot 需分别监听
- 处理函数里建议用
event.target.assignedNodes({ flatten: true })获取当前实际投射的节点列表,而不是读childNodes
connectedCallback 里立刻拿到 assignedNodes() 的完整结果 —— 得等 slotchange 或用 requestAnimationFrame 延迟读取。


















