styled-components React Native 原生支持:not()否定伪类选择器:语法、实现原理与边界
【免费下载链接】styled-componentsFast, expressive styling for React. Server components, client components, streaming SSR, React Native—one API.项目地址: https://gitcode.com/gh_mirrors/st/styled-components
本篇指南聚焦 styled-components 在 React Native 端对:not(<simple-selector>)否定伪类选择器的原生支持能力:它在当前仓库的 native-attr-operators-and-not.md 变更记录中作为 minor 版本特性被引入,覆盖伪状态取反(:not(:hover))、属性选择器取反(:not([disabled])、:not([data-state='loading']))等常用形态,同时明确了多选择器、嵌套后代选择器等复杂形态在 native 端的降级策略。阅读本文后,你将掌握在 React Native 中使用:not()的正确写法、底层解析与渲染原理,以及如何规避被忽略的规则与开发期警告。
特性概述:React Native 中的否定伪类
React Native 的样式系统在 styled-components 的驱动下支持:not(<simple-selector>)选择器:当内部条件不匹配时,规则生效。这与 CSS Selectors Level 4 §4.3 对否定伪类的定义一致——"取选择器列表作为参数的函数式伪类,表示不被其参数表示的元素的补集"。该能力在本仓库由变更集 native-attr-operators-and-not.md 声明为 styled-components 包的 minor 更新:
React Native supports
:not(<simple-selector>). Rules such as:not(:hover),:not(:focus),:not([disabled]), and:not([data-state='loading'])apply when the inner condition does not match. More complex forms, including multiple selectors or nested descendant selectors, are not supported on native: they show a development warning and are ignored.
它在已有的伪状态选择器(:hover、:focus、:focus-visible、:active、:disabled)与属性选择器(&[aria-pressed]、&[aria-pressed='true']等)之上,为"反向条件"的场景提供了一条统一语法路径,避免了使用反向布尔 props 或!important覆盖等易错方案。
支持的语法形态
伪状态取反::not(:hover)与:not(:focus)
将已知伪状态放入:not()内即得到状态取反规则。仓库的 native 测试套件 modern-css.test.tsx 用 CSS Selectors 4 §4.3 的语义对其做了规格合规验证:
const Btn = styled(StateView)` color: black; &:not(:hover) { color: red; } `;渲染结果是一个函数式样式,按 hover 状态动态解析:
- 未 hover(
{ hovered: false })→:not(:hover)成立,输出[{ color: 'black' }, { color: 'red' }] - hover(
{ hovered: true })→ 规则被反转剔除,输出[{ color: 'black' }]
:not(:focus)遵循完全相同的反转逻辑(测试 modern-css.test.tsx),{ focused: false }时触发、{ focused: true }时抑制。focus-visible与focus在 native 端映射为同一个状态(见 nativePlan.ts 中的KNOWN_PSEUDOS映射),因此取反规则同样适用。
属性选择器取反::not([disabled])与:not([data-state='loading'])
[attr]与[attr='value']两类属性选择器都可以作为:not()的内层条件:
// 属性缺失时生效 const Btn = styled.View<{ 'data-loading'?: string }>` color: black; &:not([data-loading]) { color: white; } `;测试(modern-css.test.tsx)验证了两种内层形态:
| 写法 | 触发条件 | 抑制条件 |
|---|---|---|
&:not([data-loading]) | 属性不存在时 | 属性存在(如data-loading="true") |
&:not([data-state='loading']) | 属性值不等于'loading' | 属性值等于'loading' |
这与属性选择器本身的匹配语义互补:&[data-loading]表示"存在",而&:not([data-loading])表示"不存在"。对于布尔 props,:not([data-active])同样成立——属性存在(<Btn>const KNOWN_PSEUDOS: Record<string, PseudoState> = { hover: 'hover', focus: 'focus', 'focus-visible': 'focus', active: 'pressed', disabled: 'disabled', };
第二段:桶编译 ——negate标记(compileNative.ts)
编译阶段把:not()规则编译为条件样式桶(conditional bucket),桶上的negate?: boolean字段承载取反语义:"当该标志为 true 时,matcher 反转伪状态 / 属性谓词的结果,使桶在内层选择器不匹配时触发"。从源码结构看,该标志通过pushBucket等编译函数(compileNative.ts、L1651-L1663)随伪状态桶和属性桶一起生成,并在后续传递中逐级复制(如 compileNative.ts 与 L1748 对 nthChild / 复合桶的处理),最终落入渲染期读取的ConditionalStyle条目。
第三段:渲染匹配 ——negate ? !matches : matches
运行时匹配逻辑位于 StyledNativeComponent.ts 的matchConditionals与伪状态专用匹配函数中,对各类桶统一应用取反:
- 属性桶:
attrMatches(entry, props)匹配后按entry.negate ? !matches : matches决定是否推入结果(L622-L625); - 伪状态桶:
pseudoActive(entry.condition, state)得到状态值后同样按entry.negate ? !active : active取反(L1043-L1047); - 复合形态
:not([attr]):pseudo:先要求尾随伪状态激活,再对属性匹配结果做否定——entry.negate ? attrOk : !attrOk,即属性不匹配才继续(L1049-L1054); - nthChild / has 桶:同样预留了
negate分支(L1059-L1064)。
值得注意的是,negate在渲染期的通用性表明该机制是可扩展的:除了本次:not()直接生成的桶,其他带反转标记的规则类也可复用同一匹配入口。
实践建议与注意事项
- 内层只用简单选择器:
<simple-selector>限定了支持范围,实际可写形态为单一伪状态(:not(:hover)、:not(:focus))或单一属性选择器(:not([disabled])、:not([data-state='loading'])),以及二者的复合尾随伪状态(:not([attr]):hover)。 - 复杂否定先改写再使用:
:not(:hover, :focus)、:not(.foo .bar)、:not(.foo)都会被忽略并触发开发期警告。可以拆分为多个简单规则,或在组件侧用 props 分支实现等价逻辑。 - 警告是一次性的:
warnOnce(compileNative.ts)保证同一选择器不会反复刷屏,但规则被忽略是确定的,不要依赖其生效。 - 属性匹配与布尔 props:
:not([data-active])的判定基于属性存在性,布尔 props 的隐式转换(如data-active与data-active={true})与属性选择器本身的匹配语义保持一致。 - 测试是规格的最终裁判:本特性全部行为均被 modern-css.test.tsx 中的 "
:not()spec compliance (CSS Selectors 4 §4.3)" 测试组覆盖,包括支持形态的触发/抑制矩阵与不支持形态的降级警告,可作为实现契约长期守护。
【免费下载链接】styled-componentsFast, expressive styling for React. Server components, client components, streaming SSR, React Native—one API.项目地址: https://gitcode.com/gh_mirrors/st/styled-components
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考