- 开发工具
- 代码质量
- 静态分析
【免费下载链接】eslint-plugin-react
React-specific linting rules for ESLint
导读
jsx-pascal-case是 eslint-plugin-react 提供的一条样式类(Stylistic Issues)规则,用于强制要求用户自定义的 JSX 组件在定义和引用时遵循 PascalCase 命名规范。本文以 规则文档 为骨架,结合 规则源码 与 测试用例,完整讲解该规则的触发逻辑、allowAllCaps、allowNamespace、allowLeadingUnderscore、ignore四个配置项的语义与实战用法,并深入剖析底层校验算法的实现细节,帮助你将该规则准确落地到团队 ESLint 配置中。
规则概述
规则的核心诉求是:用户自定义的 JSX 组件必须使用 PascalCase(大驼峰)命名。例如TestComponent、CSSTransitionGroup都是合规的,而Test_component、TEST_COMPONENT则会被报告为错误。
规则有一个重要的设计前提:React 的 JSX 正是依靠首字母的大小写来区分"局部组件类"与"HTML 标签"(<div />、<span />这类小写开头的标签被 React 视为内置 DOM 元素)。因此,该规则不会对小写字母开头的组件发出警告——因为小写开头的标识符在 JSX 语境下根本不会被当作自定义组件处理,也就谈不上命名检查。这一点在 测试用例 中有明确印证:<testcomponent />、<testComponent />、<test_component />均被标记为 valid。
从源码角度看,该规则挂在JSXOpeningElement节点的访问器上。它首先通过jsxUtil.isDOMComponent(node)判断当前元素是否属于 DOM 组件(即是否匹配COMPAT_TAG_REGEX = /^[a-z]/,只检测首字符),若是则直接跳过,参见 lib/util/jsx.js。随后使用elementType提取组件全名,再依次执行命名校验。
规则触发示例
不正确的写法
以下代码会被规则报告为错误:
<Test_component /><TEST_COMPONENT />在默认配置下,它们都会抛出错误消息Imported JSX component {{name}} must be in PascalCase,其中{{name}}会被替换为实际的组件名。对应的错误断言可见 测试用例。
正确的写法
<div /><TestComponent /><TestComponent> <div /> </TestComponent><CSSTransitionGroup />值得注意的细节:CSSTransitionGroup虽然是多个大写字母连续排列,但它满足 PascalCase 判定(详见下文"校验算法实现"),属于合法命名。此外,单字符组件名(如<T />)、带数字的组件名(如<Test1Component />、<T3StComp0Nent />)以及含非 ASCII 大写字母的组件(如<Éurströmming />、<Año />、<Søknad />)在测试中也都判定为 valid,说明规则对 Unicode 字符与数字有良好支持。
规则配置
规则接受一个对象作为第二项配置参数,完整 schema 如下:
"react/jsx-pascal-case": [<enabled>, { allowAllCaps: <allowAllCaps>, allowNamespace: <allowNamespace>, allowLeadingUnderscore: <allowLeadingUnderscore>, ignore: <ignore> }]各参数说明:
enabled:规则开关。0表示关闭,1表示警告,2表示错误。默认值为0。allowAllCaps:可选布尔值,设为true时允许全大写命名的组件(默认false)。allowLeadingUnderscore:可选布尔值,设为true时允许以下划线开头的组件名(默认false)。allowNamespace:可选布尔值,设为true时忽略命名空间形式的组件(默认false)。ignore:可选字符串数组,列出在校验过程中需要忽略的组件名,支持 minimatch 风格的 glob 通配符。
对应地,规则源码 中的schema声明了这四个属性均为可选,且additionalProperties: false,即不允许出现未定义的额外配置项。create函数在入口处通过context.options[0] || {}读取配置,并为四个选项设置了默认值(allowAllCaps = false、allowLeadingUnderscore = false、allowNamespace = false、ignore = [])。
选项一:allowAllCaps
当allowAllCaps为true时,以下写法视为正确:
<ALLOWED /> <TEST_COMPONENT />需要注意的是,该选项允许的是SCREAMING_SNAKE_CASE(全大写加下划线)而非任意全大写写法。从 CHANGELOG 可以看到,该选项经历了演进:"allowAllCapsoption now allowsSCREAMING_SNAKE_CASE"——即启用后规则会在 PascalCase 与 SCREAMING_SNAKE_CASE 之间取并集,任何不满足其中之一的命名都会报错。
源码中这一点体现得十分明确:当allowAllCaps开启时,规则会使用testAllCaps进行二次校验;若仍不合格,错误消息会切换为usePascalOrSnakeCase("must be in PascalCase or SCREAMING_SNAKE_CASE"),参见 lib/rules/jsx-pascal-case.js 与 lib/rules/jsx-pascal-case.js。
测试用例从正反两面覆盖了该选项的行为:
- 合法:
<YMCA />、<TEST_COMPONENT />(启用allowAllCaps); - 非法:
<TEST_COMPONENT_ />(末尾多了一个下划线)、<TEST-COMPONENT />(连字符不合法)、<__ />(allowAllCaps: true但无首字母,失败于testAllCaps首字符检查)。
这说明testAllCaps对命名结构的约束非常严格,具体规则见下文算法分析。
选项二:allowNamespace
当allowNamespace为true时,命名空间(点分隔)形式的组件被视为正确:
<Allowed.div /> <TestComponent.p />该选项针对的是成员表达式形式的组件,例如 styled-components 的Styled.h1、UI 库的Typography.P这类写法。源码中的处理逻辑是:当组件名包含.时,将名字按.拆分为数组逐段校验;而allowNamespace开启后,循环条件index < checkNames.length && !allowNamespace使得只要首段通过校验就立即跳出循环,不再继续检查后续的命名空间段,参见 lib/rules/jsx-pascal-case.js。
一个典型场景是<Styled.h1 />:默认配置下它会报错(因为h1段不符合 PascalCase),而开启allowNamespace后则通过。测试用例对此有直接对比:
- 非法(默认):
<Styled.h1 />报usePascalCase,错误数据中的name为h1; - 合法(启用
allowNamespace):<Styled.h1 />; - 非法(启用
allowNamespace):<STYLED.h1 />仍报错,因为首段STYLED本身就不是 PascalCase。
此外,<Modal.Header />、<qualification.T3StComp0Nent />在默认配置下即为合法,<Typography.P />亦然。当命名空间段只有单字符(如<$ />、<_ />)时,源码中splitName.length === 1的提前返回逻辑会直接跳过检查。
选项三:allowLeadingUnderscore
当allowLeadingUnderscore为true时,以下写法视为正确:
<_AllowedComponent /> <_AllowedComponent> <div /> </_AllowedComponent>源码中的实现是:若开启该选项且组件名以_开头,则在校验前先把开头的_去掉(splitName.startsWith('_') ? splitName.slice(1) : splitName),再对剩余部分做 PascalCase 判定,参见 lib/rules/jsx-pascal-case.js。
测试覆盖的边界情况包括:
<__ />在同时开启allowAllCaps与allowLeadingUnderscore时仍报错(去掉一个_后剩_,既不是 PascalCase 也不是全大写);<_div />在开启allowLeadingUnderscore时报错(去掉_后剩div,小写开头不满足 PascalCase);<_TEST_COMPONENT />需同时开启allowAllCaps与allowLeadingUnderscore才能通过。
重要警告:给组件名添加前导下划线不会影响组件的可见性或可访问性。试图用前导下划线来"强制私有化"组件是错误的做法——JavaScript 并不存在真正意义上的"私有组件"约定,_前缀只是命名习惯,规则仅将其视为一种可选的命名风格,而非隐私保护机制。
选项四:ignore
ignore接受一个字符串数组,用于在校验中跳过特定组件名。它支持 minimatch 风格的 glob 通配符,例如:
"react/jsx-pascal-case": ["error", { ignore: ["Foo_DEPRECATED", "*_D*D", "*_+(DEPRECATED|IGNORED)"] }]源码中的匹配逻辑位于ignoreCheck函数:先做精确的字符串相等比较,若不相等再通过minimatch(name, entry, { noglobstar: true })做 glob 匹配,参见 lib/rules/jsx-pascal-case.js。
测试用例展示了 glob 的实际效果:
<IGNORED />配合ignore: ['IGNORED'](精确匹配)通过;<Foo_DEPRECATED />配合ignore: ['*_D*D']通过(通配符匹配_D+ 任意 +D);<Foo_DEPRECATED />配合ignore: ['*_+(DEPRECATED|IGNORED)']通过(extglob 分组匹配);<Foo_DEPRECATED />配合ignore: ['*_FOO']仍然报错(模式不匹配)。
注意ignore数组的 schema 声明了uniqueItems: true,即数组中不允许出现重复项;同时minItems: 0表示允许空数组。
底层校验算法解析
PascalCase 判定(testPascalCase)
从 lib/rules/jsx-pascal-case.js 可以看出,PascalCase 的判定分三步:
- 首字符必须是大写字母:
testUpperCase(name.charAt(0))检查首字符,且要求该字符的大写形式不等于小写形式(排除数字、符号等无大小写之分的字符)。 - 其余字符中不允许出现非字母数字字符:逐个检查
name.slice(1),任何"小写等于大写"且非数字的字符(如_、-、$)都会让整段判定失败。这就是Test_component、TEST_COMPONENT报错的根本原因。 - 其余字符中必须至少有一个小写字母或数字:保证名字不是纯全大写。这一步解释了为什么
YMCA(全大写)默认报错,而CSSTransitionGroup、BetterThanCSS能通过——它们都包含小写字母。
有意思的是,testUpperCase的写法(char === upperCase && upperCase !== char.toLowerCase())天然兼容 Unicode 大写字符,因此<Éurströmming />、<Søknad />这类带变音符号的命名可以通过校验。
全大写判定(testAllCaps)
当开启allowAllCaps后,规则用 lib/rules/jsx-pascal-case.js 中的testAllCaps做补充校验:
- 首字符必须是大写字母或数字;
- 中间所有字符(索引 1 到
length - 2)必须是大写字母、数字或下划线; - 末字符必须是大写字母或数字。
这正是TEST_COMPONENT合法而TEST_COMPONENT_(末位下划线)、TEST-COMPONENT(连字符)非法的原因。
命名空间与分隔符处理
源码对:与.两种分隔符都做了处理(lib/rules/jsx-pascal-case.js):
- 名字含
:时按冒号分割(对应 JSX 命名空间语法,如<Modal:Header />); - 名字含
.时按点分割(对应成员表达式,如<Modal.Header />、<Typography.P />)。
分割后的每一段都会独立校验,且默认情况下所有段都必须通过;只有开启allowNamespace才跳过后续段。单字符段(splitName.length === 1)会被直接放行,这也是<T />、<$ />、<_ />不会报错的原因。
规则定位与启用方式
在 规则注册表 中,jsx-pascal-case被注册为jsx-pascal-case。它的meta.docs声明了:
category: 'Stylistic Issues'——属于代码风格类规则;recommended: false——不在 recommended 预设配置中,需要团队显式开启。
由于它未被纳入 configs/all.js、configs/recommended.js 的默认预设,启用方式是在 ESLint 配置文件中显式声明。传统 eslintrc 格式:
"rules": { "react/jsx-pascal-case": ["error", { "allowAllCaps": false, "allowNamespace": false, "allowLeadingUnderscore": false, "ignore": [] }] }扁平化(flat config)格式:
export default [ { files: ['**/*.{js,jsx,ts,tsx}'], plugins: { react: reactPlugin }, rules: { 'react/jsx-pascal-case': ['error', { allowAllCaps: false }], }, }, ];规则在仓库中的演进也值得关注。CHANGELOG 记录了一系列针对性修复:支持 Unicode 字符、修复H1误报(<H1>是合法 HTML 标签,不应被当作自定义组件)、支持 minimatchignore、新增allowNamespace、新增allowLeadingUnderscore、单字符命名空间组件处理等。这些历史变更说明该规则在真实项目中经过了长期打磨,边界情况(数字、Unicode、成员表达式、命名空间、单字符)都已有测试覆盖。
何时不使用此规则
如果你没有使用 JSX(例如纯 JavaScript 项目、或使用其他模板语言),则该规则没有任何意义,可以直接关闭。此外,如果团队项目中有大量既有的非 PascalCase 组件命名且短期无法重构,可以先通过ignore数组逐步豁免,或暂时降级为"warn"观察期,再逐步收紧为"error"。
小结
jsx-pascal-case用一条简单但严谨的规则,将 JSX 自定义组件命名统一到 PascalCase,充分利用了 React "首字母大小写区分组件与 DOM 标签"的语义约定,避免了Test_component、TEST_COMPONENT这类容易引发混淆的命名。通过allowAllCaps、allowNamespace、allowLeadingUnderscore与ignore四个选项,它又能灵活适配 styled-components、命名空间组件、全大写常量组件等真实场景,是值得在每个 React 项目中启用的一条低成本高收益的代码风格规则。
- 开发工具
- 代码质量
- 静态分析
【免费下载链接】eslint-plugin-react
React-specific linting rules for ESLint
相关推荐
使用 eslint-plugin-react 的 react/require-render-return 规则:强制类组件 render 方法返回 JSX
使用 eslint plugin react 的 react/require render return 规则:强制类组件 render 方法返回 JSX re
开发工具代码质量静态分析eslint-plugin-react 的 react/self-closing-comp 规则:强制无子元素 JSX 组件使用自闭合标签
eslint plugin react 的 react/self closing comp 规则:强制无子元素 JSX 组件使用自闭合标签 本篇技术指南围绕 e
开发工具代码质量静态分析用 Takumi 构建 GitHub PR 代码审查工作流:以 Umi 仓库的 review 命令为例
用 Takumi 构建 GitHub PR 代码审查工作流:以 Umi 仓库的 review 命令为例 导读 本文围绕 Umi 仓库内 .takumi/comm
开发工具代码质量静态分析
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考