slot标签仅在启用Shadow DOM时生效,需满足三条件:自定义元素已注册、调用attachShadow()、外部内容为直系子节点且slot位于Shadow DOM内;::slotted()仅匹配直系子节点,不支持嵌套选择器或伪类。

slot 标签本身不生效,除非你已启用 Shadow DOM;样式隔离也只在 Shadow DOM 内真正成立——没调用 attachShadow(),就只是普通 HTML 片段。
为什么写了 slot 却没内容显示
这不是浏览器 bug,而是机制未触发。三个硬性条件缺一不可:
- 自定义元素必须通过
customElements.define()注册,且在constructor或connectedCallback中调用this.attachShadow({ mode: 'open' }) - 外部传入的内容必须是该自定义元素的**直系子节点**:
<my-card><h2 slot="header">标题</h2></my-card>✅;<my-card><div><h2 slot="header">标题</h2></div></my-card>❌(<div>隔断了投射链) -
<slot>标签必须写在 Shadow DOM 模板里(例如克隆<template>后 append 到shadowRoot),不能直接写在 Light DOM 中
::slotted() 样式为什么总不生效
它不是“让外部内容变色”的万能钩子,而是一个有严格边界的穿透通道:
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
- 只匹配被分发进来的**直系子节点**:
::slotted(h2)有效,::slotted(div h2)或::slotted(.header h2)完全无效 - 不继承、不冒泡、不支持伪类:
::slotted(h2:hover)不合法,::slotted(p::first-line)也不行 - Light DOM 的全局样式(如
p { color: red; })依然会命中 slot 内容——::slotted()不是隔离开关,只是单向样式透传入口 - 想控制更深层结构?得把那部分也封装成带 Shadow DOM 的自定义元素,而不是靠嵌套选择器
如何验证插槽是否真被分配了内容
别靠肉眼判断渲染结果,用 API 查实时状态:
立即学习“前端免费学习笔记(深入)”;
- 在自定义元素内部执行
this.shadowRoot.querySelector('slot[name="header"]').assignedNodes(),返回空数组说明没内容进来 -
assignedNodes({ flatten: true })可展开默认插槽的嵌套文本节点,但注意:哪怕只有一个空格或换行符,也会算作文本节点,导致 fallback 不显示 -
slotchange事件只在分配关系变更时触发(如动态增删子节点),首次挂载不触发,别指望它初始化时就 fire - 调试时优先用
assignedElements(),它自动过滤掉纯文本节点,更适合判断“有没有实际元素被塞进来”
真正难的不是写对语法,而是接受 Shadow DOM 的“投影”本质:内容从没离开 Light DOM,slot 只是窗口,不是搬运工;样式不自动隔离,::slotted() 也不是快捷键——它要求你明确声明每一处穿透意图。漏掉 attachShadow(),所有 slot 和样式隔离逻辑都退化为无意义的字符串。


















