::part()仅匹配shadow root内真实DOM节点的静态part属性,需手动在内部元素添加如part="label",且exportparts须逐层显式转发,命名即公开API不可随意变更。

part 属性必须写在 shadow root 内的真实节点上
外部写 my-input::part(label) 没反应,八成是组件内部根本没在任何元素上加 part="label"。::part() 不是穿透工具,它只匹配 shadow tree 里**真实 DOM 节点**上声明的静态 part 值。
常见错误现象:
-
<slot name="label"></slot>上写part="label"—— 无效,<slot>是占位符,不是真实节点 - 用模板字符串动态绑定:
part={this.type}或:part="error"—— 浏览器直接忽略,part必须是纯静态字符串 - 把
part="icon"写在宿主标签上,比如<my-button part="icon"></my-button>—— 宿主自身不参与 ::part() 匹配,只看 shadow 内部
正确做法:打开 DevTools → 展开 shadow root → 找到目标元素(如 <span class="label">),手动加上 part="label"。同一个节点可写多个值:part="label required error",外部就能分别用 ::part(required) 或 ::part(error) 选中。
exportparts 是跨层暴露的显式转发机制
如果组件嵌套了另一层自定义元素(比如 <my-form> 里用了 <my-input>),想让最外层直接控制 <my-input> 内部的 part="input",不能靠“自动透传”——必须逐层用 exportparts 显式声明。
立即学习“前端免费学习笔记(深入)”;
关键规则:
-
exportparts只作用于**直接子组件**,写在<my-form>上的exportparts="input"对<my-input>里的part="input"无效,除非<my-form>的 shadow 内是直接渲染<my-input exportparts="input"> - 语法固定为
"source-part-name=target-part-name",例如exportparts="input=field",外部就只能用::part(field),不能再用::part(input) - 大小写、连字符、空格必须完全一致,
exportparts="Input"和part="input"不匹配
漏掉任意一层,链就断了。Chrome DevTools 里看到样式生效,未必是 exportparts 起效——可能是 color 等可继承属性自然传递,得靠 background-color 这类非继承属性验证。
::part() 兼容性不能只看 CanIUse
Chrome/Edge 97+ 原生支持,没问题;但 Safari 从 15.4 开始才支持,且需用户手动开启 about:config 中的 Experimental Web Platform Features;Firefox 截至 2026 年 5 月仍未实现,@supports selector(::part(foo)) 永远返回 false。
真实部署底线:
- iOS 16.7 + Safari 必须能跑通
- macOS 12.6 + Safari 是最低测试环境
- 企业内网大量旧设备卡在 macOS + Safari 15.3 或更早,
::part()直接不可用
所以不能把 ::part() 当基础能力用。核心样式必须靠 CSS 变量 fallback:color: var(--my-input-label-color, #333);,再用 @supports selector(::part(foo)) { ... } 包裹增强部分。
part 名称是公开 API,改名等于 breaking change
一旦在组件中公开 part="submit",第三方使用者就会在 CSS 里直接写 my-button::part(submit)。后续你想改成 part="primary-action",所有依赖方都会失效。
真正容易被忽略的是命名约束:
- 避免缩写歧义,
part="btn"和part="button"应该统一选一个 - 不要用数字或特殊符号开头,
part="1st"或part="-icon"在某些解析器里可能出问题 - 嵌套组件暴露的
part名最好带前缀,比如part="inner-loader",避免和宿主层级冲突
没有后悔药。定下 part 名之前,先想清楚它会被谁用、怎么用、会不会长期存在。



















