Introduction
踏上新的职业旅程时,往往伴随着兴奋和高期望。然而,当面对一个类似混乱拼图的代码库时,现实可能迥然不同。为了缓解这一常见情况,特别是对于担任高级职位的开发者而言,采用特定的最佳实践变得至关重要。这不仅确保了代码的质量,也让你作为一个细致的专业人士,获得公司内的认可和潜在晋升。
1. 最优路径处理:绝对路径优于相对路径
想象一下,只有像"往回走四步然后向左转两次"这样隐晦的提示,你要在迷宫中找到出路。这就是在你的代码中使用相对路径的感觉。相反,拥抱绝对路径的力量吧!绝对路径提供了文件的完整地址,使得导入变得清晰明了,从而避免了无休止的猜测游戏。虽然设置它们可能需要用到Webpack或TypeScript之类的工具进行一些配置魔法,但相信我们,这努力是值得的。
额外提示:对于使用create-react-app的项目来说,一个简单的jsconfig.json文件可以成为你的英雄。通过几行代码,你可以为导入定义一个基础URL,将那个冗长的路径../../../../../components/Button
转变为简洁的@/components/Button
。
如果你正在使用TypeScript,请在你的"tsconfig.json"文件中添加以下配置:
JSON
{
"compilerOptions": {
"baseUrl": "src",
"paths": {
"@/*": ["src/*"]
}
},
"include": ["src"]
}
通过这样做,你可以将一个代码片段转变成如下所示:
TypeScript
//from this
import { Button } from '../../../../components/Button'
import { Icon } from '../../../../components/Icon'
import { Input } from '../../../../components/Input'
Into something cleaner and easier to read, like:
//to this
import { Button } from '@/components/Button'
import { Icon } from '@/components/Icon'
import { Input } from '@/components/Input'
2. 精简模块组织:『Export Barrel』的力量
使用export barrel 技术,又称之为re-export ,可以大幅提升代码的可读性和维护性。在一个文件夹内创建一个index.js
(或对于TypeScript
来说是index.ts
)文件,并导出所有模块,这样可以简化导入过程并增强代码的组织性。 实现示例: 想象有一个名为components
的文件夹,里面包含Button.tsx
、Icon.tsx
和Input.tsx
。通过使用export barrel ,你可以创建一个"index.ts
文件来简化导入过程:
TypeScript
export * from './Button'
export * from './Icon'
export * from './Input'
这种做法不仅减少了单独导入的需求,而且有助于实现更干净、更易理解的代码库------这对中到大型项目至关重要。
3. 在"默认导出"和"命名导出"之间进行选择
当我们深入探讨export barrel
这个话题时,必须指出它可能与export default
的使用发生冲突。如果这还不够清楚,我会用例子来说明这种情况:
让我们回到我们的组件:
TypeScript
// button.tsx
export const Button = () => {
return <button>Button</button>
}
export default Button
// icon.tsx
export const Icon = () => {
return <svg>Icon</svg>
}
export default Icon
// input.tsx
export const Input = () => {
return <input />
}
export default Input
想象一下,这些组件中的每一个都在一个单独的文件中,而你想要一次性导入它们全部。如果你习惯于使用默认导入,你可能会尝试像这样做:
TypeScript
import Button from '@/components'
import Icon from '@/components'
import Input from '@/components'
然而,这种方法行不通,因为JavaScript无法确定应该使用哪个默认导出,这会导致错误。你将不得不采取如下措施:
TypeScript
import Button from '@/components/Button'
import Icon from '@/components/Icon'
import Input from '@/components/Input'
然而,这否定了export barrel
的优势。怎样才能解决这一难题呢?解决方案很简单:使用Named Export
,也就是不使用"default"来导出:
TypeScript
import { Button, Icon, Input } from '@/components'
与默认导出相关的另一个关键问题是可以重命名你正在导入的内容的能力。我将分享我职业生涯早期的一个真实例子。我接手了一个React Native项目,之前的开发者对所有东西都使用了export default
。有些屏幕被命名为"Login"、"Register"和"ForgotPassword"。然而,这三个屏幕彼此之间是复制的,只有细微的修改。问题在于,每个屏幕文件的末尾都有一个export default Login
。这导致了混乱,因为路由文件的导入确实是正确的:
JavaScript
import Login from '../../screens/Login'
import Register from '../../screens/Register'
import ForgotPassword from '../../screens/ForgotPassword'
JavaScript
// Further down, the usage in routes:
{
ResetPassword: { screen: ResetPassword },
Login: { screen: LoginScreen },
Register: { screen: RegisterScreen },
}
但是打开屏幕文件时,它们都导出了相同的名称:
TypeScript
const login() {
return <>tela de login</>
}
export default Login
const login() {
return <>tela de registro</>
}
export default Login
const login() {
return <>tela de esqueci minha senha</>
}
export default Login
这导致了一个维护噩梦,不断的混乱和需要极度的警惕来避免错误。
总之,在你的项目中大多数情况下高度推荐使用命名导出
,并且只在绝对必要时才使用export default
。有些情况,如 Next.js 路由和 React.lazy,可能需要使用export default
。然而,平衡代码清晰度和遵守特定要求是至关重要的。
4. 正确的文件命名规范
让我们想象你有一个包含以下文件的组件文件夹:
Plain
-components:
----Button.tsx
----Icon.tsx
----Input.tsx
现在,假设你想要将这些组件的样式、逻辑或类型分离到不同的文件中。你会怎么命名这些文件呢?一个显而易见的方法可能是如下所示:
Plain
--components:
----Button.tsx
----Button.styles.css
----Icon.tsx
----Icon.styles.css
----Input.tsx
----Input.styles.css
当然,这种方法看起来可能有些杂乱无章,而且难以理解,特别是当你打算将组件进一步划分为不同的文件,比如逻辑或类型时。但你怎样才能保持结构的有序呢?这里有个解决方案:
Plain
--components:
----Button
------index.ts (exports everything necessary)
------types.ts
------styles.css
------utils.ts
------component.tsx
----Icon
------index.ts (exports everything necessary)
------types.ts
------styles.css
------utils.ts
------component.tsx
----Input
------index.ts (exports everything necessary)
------types.ts
------styles.css
------utils.ts
------component.tsx
这种方法使得识别每个文件的目的变得简单,并且简化了寻找所需内容的过程。此外,如果你在使用 Next.js 或类似的框架,你可以调整文件命名来标明该组件是用于客户端还是服务器端。例如:
Plain
--components:
----RandomComponent
------index.ts (exports everything necessary)
------types.ts
------styles.css
------utils.ts
------component.tsx
----RandomComponent2
------index.ts (exports everything necessary)
------types.ts
------styles.css
------utils.ts
------component.server.tsx
通过这种方式,无需打开代码进行验证就极其简单地区分一个组件是用于客户端还是服务器端。组织和标准化文件命名对于保持开发项目的清晰度和效率至关重要。
5. 正确使用 ESLint 和 Prettier 进行代码规范化
想象一下,你在和超过10位同事一起参与一个项目,每个人都带来了他们以往经验中的编码风格。这就是 ESLint 和 Prettier 发挥作用的地方。它们在维持团队代码一致性中扮演着至关重要的角色。
Prettier 充当一种代码格式的"守护者",确保每个人都遵循为项目设置的样式指南。例如,如果项目标准规定使用双引号,你就不能简单地选择使用单引号,因为 Prettier 会自动将其替换。此外,Prettier 还可以进行各种其他修复和格式化,如代码对齐、在语句末尾添加分号等。你可以在官方文档中查看特定的 Prettier 规则:Prettier 选项。
另一方面,ESLint 强制在代码上实施特定规则,帮助维护一个有凝聚力和连贯性的代码库。例如,它可以强制使用箭头函数而不是常规函数,确保 React 依赖数组正确填充,禁止使用 var
声明而优先选择 let
和 const
,并应用像 camelCase 这样的命名约定。你可以在官方文档中找到特定的 ESLint 规则:ESLint 规则。
ESLint 和 Prettier 的联合使用有助于维护源代码的一致性。没有它们,每个开发者都可以遵循自己的风格,这可能导致未来出现冲突和维护困难。设置这些工具对于项目的长期性至关重要,因为它有助于保持代码的组织性和易于理解性。如果你还没有使用 ESLint 和 Prettier,认真考虑将它们纳入你的工作流程,因为它们会极大地惠及你的团队和整个项目。
总结:
通过将这些最佳实践融入到你的React开发流程中,你将有助于创建一个更有组织、可读性更强、且更易于维护的代码库。保持致力于提升编码标准。