::part()不是穿透工具,仅在组件作者显式声明exportparts且shadow内节点含静态part属性时生效;未暴露或写在slot中、动态绑定、closed shadow、不兼容浏览器均导致my-card::part(title)完全无效。

::part() 不是“穿透”工具,它只在组件作者明确开放的前提下才起作用;没写 exportparts、没在 shadow 内节点上加静态 part 属性,外部写再多 my-card::part(title) 都不会生效。
为什么 my-card::part(title) 完全不生效
根本原因不是浏览器不支持,而是样式目标根本不存在:
- 检查
my-card的 shadow root 里是否存在真实 DOM 节点(比如<h2 part="title"></h2>),而不是写在<slot></slot>上或 slot 分发进来的外部内容上 -
part必须是静态字符串:part="title"有效,:part="title"(Vue 绑定)或part={this.titlePart}(JSX)全部无效 - 若组件用了
attachShadow({ mode: 'closed' }),::part()直接不可用——它只对mode: 'open'生效 - iOS 16.7 之前的 Safari、macOS 12.6 之前的 Safari、所有版本 Firefox(截至 2026 年 5 月)都不支持
::part(),@supports selector(::part(foo))永远返回false
exportparts 是强制开关,不是可选项
即使 shadow 内节点写了 part="header",若自定义元素没声明 exportparts,外部依然无法选中。这是 Web Components 规范的显式授权机制:
- 在自定义元素定义时必须显式导出:
exportparts="header:title header-icon:icon footer:footer" - 导出名(冒号右边)才是外部 CSS 中
::part()实际匹配的值:my-card::part(title)→ 匹配的是exportparts中的title,不是节点上的part="header" - 多个内部 part 可映射到同一个导出名:
exportparts="title:card-title, subtitle:card-title",方便统一控制 - 未导出的 part 名称对外部完全不可见,也不会出现在 DevTools 的 Styles 面板中
如何安全 fallback 到 CSS 自定义属性
把 ::part() 当作渐进增强层,核心样式必须靠 var(--my-card-title-color, #333) 支撑:
- 宿主上设变量:
<my-card style="--my-card-title-color: #1e1e1e;"></my-card> - shadow 内消费时必须带 fallback:
color: var(--my-card-title-color, #333); - 用
@supports selector(::part(foo))包裹定制样式,避免旧浏览器解析失败或报错 - 别在 shadow 内写
:host { --my-card-title-color: blue; }试图“反向暴露”,它只影响宿主自身,不向外传递 - 微前端场景下,若子应用启用了
strictStyleIsolation: true(如 qiankun),my-card::part(title)只能匹配 host 元素本身,不能深入其 shadow 内部节点——后者需由子应用自己导出并注入规则
真正容易被忽略的是:part 名称一旦定下,就是公开 API;第三方使用者会直接依赖它,改名等于 breaking change。而 exportparts 的映射关系更隐蔽,一旦漏掉或拼错,调试时连样式面板里都看不到对应规则。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











