使用Emotion时:first-child报错且替换为:first-of-type不符合需求如何解决?
问题原因解析
为什么Emotion会触发:first-child警告
Emotion的该报错是为了规避SSR(服务端渲染)场景下的hydrate不匹配问题:如果组件在服务端渲染和客户端注水时的子元素数量、顺序存在差异,:first-child这类和子元素位置强绑定的伪类会出现两端匹配结果不一致的问题,因此Emotion默认会对这类选择器做安全提醒。
为什么:first-of-type达不到预期效果
:first-of-type的匹配规则是按标签类型匹配同类型下的第一个子元素,你的DOM结构中存在span和div两种标签:
- 第一个
span(类名one)是span类型的首个元素 - 第一个
div(类名two)是div类型的首个元素
因此*:not(:first-of-type)会同时排除这两个元素,只有第三个的span(类名three)和第四个的div(类名four)会命中样式,和你想要的「排除所有子元素中的第一个,其余全部变红」的需求不符。
解决方案
方案1:使用* + *相邻兄弟选择器(最优解)
该选择器的匹配规则是「匹配所有前面存在相邻兄弟元素的子元素」,效果和你原来写的:not(:first-child)完全一致,且不会触发Emotion的SSR安全警告:
.parent { & > * + * { color: red; } }
方案2:临时忽略当前选择器的警告
如果你能100%确认当前父组件的子元素结构在服务端和客户端完全一致,没有动态插入/删除子元素的逻辑,可以加特殊注释关闭当前行的警告:
.parent { /* emotion-disable-server-rendering-unsafe-selector-warning */ & > *:not(:first-child) { color: red; } }
方案3:手动给首个子元素加专属类名
如果可以控制子元素的渲染逻辑,直接给第一个子元素加专属类名匹配,完全规避位置类伪类的风险:
<div class="parent"> <span class="one first-child">1</span> <div class="two">2</div> <span class="three">3</span> <div class="four">4</div> </div>
对应样式:
.parent { & > *:not(.first-child) { color: red; } }
内容的提问来源于stack exchange,提问作者Chilyan
相关产品推荐
相关产品推荐

