::part() 是组件作者主动暴露的样式锚点,仅匹配 shadow DOM 中真实存在且大小写严格匹配的 part 属性,不支持选择器链、伪元素或动态绑定,需依赖 exportparts 透传嵌套部分,且 Firefox 尚未原生支持。

::part() 不能“突破”封装限制,它只是组件作者主动开放的一个样式锚点——没暴露就完全不可用,不是开关,也不是穿透工具。
为什么 ::part(icon) 写对了却没反应
因为浏览器只匹配 shadow DOM 内部真实存在 part="icon" 属性的元素,不报错、不警告、不提示,静默跳过。
- 检查方式:在 DevTools 中右键组件 → “Inspect”,进入 shadow root 后手动搜索
part="icon"(注意大小写严格匹配) -
part="Icon"和::part(icon)不匹配;part="icon required"可被::part(required)单独选中 - 宿主元素(如
<my-button>)自身不能加part属性,::part()只作用于 shadow 内部子节点 - 动态绑定无效:
part={this.state.type}或:attr(part)都不会触发样式计算
::part() 的语法边界在哪
::part() 是单点锚定伪元素,不是选择器链起点,后面不能接任何其他选择器。
- 非法写法:
my-input::part(wrapper) input、my-button::part(label)::before、:host::part(label) - 合法写法只有:
my-button::part(label),所有样式必须直接定义在这个伪元素上 - 不支持伪元素(
::before)、属性选择器([disabled])、关系选择器(>、+)跟在::part()后面 - 同一节点可声明多个 part:
part="label required error",外部可用::part(required)单独命中
嵌套 Shadow DOM 怎么让 ::part() 生效
如果组件内部还包含另一个自定义元素(比如 <editor-toolbar>),外部 ::part() 默认无法穿透到它的 shadow 内部。
立即学习“前端免费学习笔记(深入)”;
- 必须由外层组件通过
exportparts="toolbar:inner-toolbar"显式透传 - 然后外部才能写
my-editor::part(inner-toolbar),而不是my-editor::part(toolbar) - 透传是逐层的:A → B → C,每层都得用
exportparts显式声明,缺一层就断掉 -
exportparts必须写在宿主元素标签上,不是 shadow 内部的<style>里
兼容性和降级必须做
Chrome 97+、Edge 97+ 原生支持;Safari 自 15.4 起支持但需开启实验性功能;Firefox 截至 2026 年 8 月仍不支持——@supports selector(::part(foo)) 在 Firefox 中永远返回 false。
- 必须用
@supports包裹::part()规则,并提供降级方案(如 CSS 自定义属性) - 不要指望
!important或全局 class 能绕过限制,它们对未暴露的 part 完全无效 - 组件作者若没加
part,调用方没有任何办法补救——这是设计使然,不是 bug
最常被忽略的一点:::part() 生效的前提是组件作者已经做了两件事——在 shadow 内部节点上写死 part="xxx",且在需要透传时配好 exportparts。你写的每一行 ::part() 样式,本质上都是在依赖别人的代码是否完备。


















