styled-components React Native 原生支持 `:not()` 否定伪类选择器:语法、实现原理与边界
2026/9/19 17:43:39 网站建设 项目流程

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-visiblefocus在 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()直接生成的桶,其他带反转标记的规则类也可复用同一匹配入口。

实践建议与注意事项

  1. 内层只用简单选择器<simple-selector>限定了支持范围,实际可写形态为单一伪状态(:not(:hover):not(:focus))或单一属性选择器(:not([disabled]):not([data-state='loading'])),以及二者的复合尾随伪状态(:not([attr]):hover)。
  2. 复杂否定先改写再使用:not(:hover, :focus):not(.foo .bar):not(.foo)都会被忽略并触发开发期警告。可以拆分为多个简单规则,或在组件侧用 props 分支实现等价逻辑。
  3. 警告是一次性的warnOnce(compileNative.ts)保证同一选择器不会反复刷屏,但规则被忽略是确定的,不要依赖其生效。
  4. 属性匹配与布尔 props:not([data-active])的判定基于属性存在性,布尔 props 的隐式转换(如data-activedata-active={true})与属性选择器本身的匹配语义保持一致。
  5. 测试是规格的最终裁判:本特性全部行为均被 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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询