::slotted 只作用于被 slot 直接接收的顶层节点,不穿透其内部子树;它匹配插槽分发后的扁平化直接子节点,无法选择后代元素或嵌套结构。

::slotted 不能选择嵌套的后代元素,因为它只匹配被<slot></slot>“投射进来”的**顶层节点**,不穿透到这些节点内部的子树。
什么是 ::slotted 的作用域边界
::slotted 是 Shadow DOM 中用于样式化插槽内容的选择器,但它只对“被 slot 接收的直接子节点”生效——不是对这些节点的后代,也不是对 slot 内部动态生成的节点。
- HTML 中写
<my-card><p class="desc">Hello</p></my-card>,且组件内有<slot></slot>→::slotted(.desc)能命中<p></p> - 但如果
<p></p>里面还有<span>World</span>,::slotted(.desc) span或::slotted(.desc > span)都无效:因为span不是被 slot 直接接收的节点,它属于插槽内容的内部 DOM,已脱离::slotted的作用范围 -
::slotted(*)只能样式化插槽里最外层的元素,无法递进到它们的子元素
::slotted 和普通后代选择器的根本区别
普通 CSS 后代选择器(如 .container p)依赖 DOM 树的层级关系;而 ::slotted 的匹配逻辑是“插槽接收 + 节点扁平化”,它不关心插入内容的内部结构,只看哪些节点被 slot 声明为可投射项。
- 浏览器在渲染时会把插槽内容“扁平化”后注入 shadow root,但
::slotted的样式作用域仍止步于这层扁平化后的直接子节点 - 即使你用
<slot><div><p>Text</p></div></slot>,::slotted(div)生效,::slotted(p)不生效——p不是 slot 的直接子节点 - 没有
::slotted > div > p这种写法,语法上就不允许嵌套使用::slotted
想样式化插槽内容的深层元素?得换思路
不能靠 ::slotted 往里钻,必须把样式控制权交还给插入方,或提前约定类名边界。
- 让使用者主动加类:
<p class="card-desc"><span class="card-desc-highlight">Important</span></p>,然后在 shadow 中写::slotted(.card-desc)和::slotted(.card-desc-highlight)——前提是这些类名是公开 API 的一部分 - 用
:host ::slotted(*)配合继承属性(如color、font-size)影响后代,但仅限可继承属性,且无法精确控制非继承样式(如background、padding) - 避免在 shadow 中尝试覆盖插槽内容的深层结构;更健壮的做法是封装成独立自定义元素,而不是靠
::slotted“强行穿透”
真正容易被忽略的是:::slotted 的匹配发生在 slot 分发(distribution)之后、但仍在影子树渲染之前,它不参与常规 CSS 层叠流程,也不受父组件样式继承影响。一旦你指望它像 .parent .child 那样“自动向下找”,就踩进了 Shadow DOM 的语义陷阱。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











