这篇文章发布于 2025年11月17日,星期一,15:48,归类于 CSS相关。 阅读 93 次, 今日 92 次 没有评论
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11897
本文可全文转载,但需要保留原作者、出处以及文中链接,AI抓取保留原文地址,任何网站均可摘要聚合,商用请联系授权。
一、你需要提前知道的
Web Components组件开发又新增新特性,为:state()伪类函数。
4年多前,有介绍过::part()伪元素函数,可以穿透组件内部,对里面的样式进行设置。
详见这篇文章:“使用::part伪元素改变Shadow DOM的CSS样式”
而:state()伪类函数,则是穿透组件内部,匹配状态进行样式设置。
你可以理解为,::part()伪元素函数更像是 [disabled] 这种属性选择器,需要内部HTML有对应的属性设置(通过设置part属性)才能匹配,但是:state()伪类函数更像是 :disabled 这类伪类选择器,看中的是元素的真实状态,而非是否有这个属性。
attachInternals方法
那如何给组件设置状态,让:state()伪类函数匹配呢?这个就需要用到今年年初介绍的attachInternals方法。
可以访问这里了解:“研究下attachInternals方法,可让普通元素有表单特性”
例如:
const someInternals = someCustomElement.attachInternals()
而这个someInternals就是个ElementInternals对象,其包含一个名为states的属性(见下图)。

states属性的返回值是一个CustomStateSet对象,包含以下一些属性和方法:
// 属性 CustomStateSet.size
// 方法 CustomStateSet.add() CustomStateSet.clear() CustomStateSet.delete() CustomStateSet.entries() CustomStateSet.forEach() CustomStateSet.has() CustomStateSet.keys() CustomStateSet.values()
我们日常开发,用的比较多的讲就是add()方法添加状态,delete()方法删除状态。
二、:state()函数案例
一例胜千言,让我想想,弄个什么案例好呢……要经典,又要具有代表性,嗯……算了,随便示意下效果吧。
JS和CSS代码如下所示:
class UiLoading extends HTMLElement {
constructor() {
super();
const internals = this.attachInternals();
this.addEventListener('click', () => {
internals.states.add('loading');
setTimeout(() => {
internals.states.delete('loading');
}, 3000);
});
}
connectedCallback() {
this.click();
}
}
// 定义自定义组件
if (!customElements.get('ui-loading')) {
customElements.define('ui-loading', UiLoading);
}
ui-loading {
display: inline-grid;
place-items: center;
width: 150px; height: 150px;
border: 2px dashed;
}
ui-loading:state(loading) {
border-color: red;
background: lightgreen;
}
此时,只要页面上有 <ui-loading> 元素,就可以看到样式变化了。
默认是绿底红框,几秒钟时候,就是黑框了。
实时效果如下所示,如果看不到效果,请点击下面的框框。
可以看到,:state()函数的设计初衷就是为了方便暴露组件内部的状态。
例如,选中与否,失败与否,加载与否等。
三、兼容性与结语
CSS :state()伪类函数在2024年5月份的时候,已经被所有现代浏览器都支持,大规模应用的时机还不成熟,不过不得不说,这个东西可以提高组件开发的档次感(虽然part属性和::part()函数也能实现类似效果,但没有这个看起来高大上)。

总结
:state() 伪类是未来 Web 组件样式化的一个强大且语义化的工具。它将样式控制的逻辑从“如何渲染”(暴露内部部件)转变为“在什么状态下渲染”,使得组件开发者能更好地封装内部结构,同时为组件使用者提供清晰、强大的样式定制能力。
吐槽
昨天遇到个难受的事情,我鱼竿包里翻来覆去,我的一根鱼竿不见了,达亿瓦一击枫,是我买的价格比较高的杆子之一,用了很多年了,也比较有感情了。
思来想去,是上周在情人谷垂钓园钓鲫鱼的时候,没有及时收起来,搁在了河边,走的时候,只收了另外一只杆子,同时损失的还有一只浮漂。
好难受,钓鱼这么多年,还是头一次丢杆子。
打电话给老板,老板也没见到,估计被人捡走了。
郁闷!
鱼没有钓到几条,杆子没了,我都不敢告诉家里人,不然又要吐槽丢三落四,只能悄悄又买了个新杆子。
舍不得买贵的,就买了个200不到的,唉……

本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11897
(本篇完)
- 巧用两个type=range input实现区域范围选择 (0.531)
- Safari不支持build-in自定义元素的兼容处理 (0.531)
- 研究下attachInternals方法,可让普通元素有表单特性 (0.531)
- 垃圾特性之CSS :heading伪类和:heading()函数 (0.469)
- HTMLUnknownElement与HTML5自定义元素的故事 (0.281)
- 聊聊JS DOM变化的监听检测与应用 (0.281)
- CSS技术分享: 文字在圆形内沿着弧线边界排版 (0.281)
- 了解CSS min()/max()/clamp()数学函数 (0.281)
- 纯CSS实现未读消息超过100自动显示为99+ (0.281)
- 如何继承自定义元素及其他JS中扩展新方法 (0.281)
- Selectivizr-让IE6~8支持CSS3伪类和属性选择器 (RANDOM - 0.188)