React组件入门:构建可复用、易维护的UI组件
了解为何将 UI 拆分为小型 React 组件能提升可重用性、可读性以及团队协作效率,随后创建你的第一个功能组件。
每位前端开发者都熟悉的场景
想象一下:这是你在一家新创公司工作的第一周。
你的经理走到你办公桌前对你说:
"主页必须在周五之前完成。"
你打开 Figma 设计文件。
它由以下部分组成:
- 顶部导航菜单
- 大型标题横幅
- 搜索栏区域
- 特色产品展示区
- 客户评价板块
- 价格表
- 常见问题解答区
- 新闻订阅表单
- 网站页脚
这项任务看起来相当简单。
你创建了一个 HTML 文件,然后按顺序开始构建每个部分。
到了周五,所有工作都完成了。
一切运行正常。
你为此感到非常满意。
一个月后,产品功能得到了扩展。
营销团队希望设计新的横幅。
设计师们重新设计了导航栏。
产品团队希望增加一个价格层级板块。
现在客户评价需要动态加载。
不知不觉中,那个文件的内容已经超过了2,000行。
要找到某个按钮简直就像在代码迷宫中寻找线索。
更糟糕的是,稍微修改页面的某个部分就可能会破坏其他完全无关的功能。
这种情况听起来熟悉吗?
正是这样的痛点促使开发者们寻求构建界面的新方法。
与其创建一个庞大的页面,何不将其拆分成许多小型、可重复使用的组件呢?
在React中,这些组件就被称为Components。
为何单个巨大文件会出问题
想象一下用传统方式构建的典型网页。
Homepage.html
---------------------------------------------------
Navigation
Hero Section
Featured Products
About Us
Testimonials
Pricing
FAQ
Newsletter
Footer
---------------------------------------------------
页面的每个部分都存在于那个文件中。
随着项目规模扩大,你会遇到以下问题:
- 文件大小持续增加。
- 团队协作变得更加困难。
- 没有任何内容可以真正被复用。
- 错误出现的频率越来越高。
- 维护代码变得极为耗力。
现在来看看 React 是如何处理同一页面的。
App
│
├── Navbar
├── Hero
├── Products
│ ├── ProductCard
│ ├── ProductCard
│ └── ProductCard
├── Testimonials
├── FAQ
└── Footer
无需将所有内容塞进一个文件,每个部分都可以成为独立的单元。
这种模式被称为基于组件的架构。
定义 React 组件
从根本上说,组件只不过是一段可复用的用户界面代码。
你可以将其视为一个返回 JSX 的 JavaScript 函数。
不必将整个页面打包到一个文件中,而应将其拆分成多个更小、功能更明确的模块。
每个模块仅负责一项任务。
例如:
导航栏成为独立的组件。
页脚也是另一个组件。
产品卡片则是又一个组件。
用户资料部分同样属于一个组件。
随后再将这些组件组合起来,形成完整的应用程序。
这样得到的代码库更易于阅读、测试,并且便于长期维护。
改变对 UI 的思维方式
这是学习 React 时需要做出的最重要思维转变之一。
不要再以整个页面来思考问题。
而应从单个模块的角度出发。
不要问:
“我该如何构建这个首页?”
可以试着这样问:
“构成这个主页的更小的组件有哪些?”
一旦理解了这个思路,React 会显得直观得多。
日常类比
想象一下搭建乐高城市。
每次需要砖块时都不会去制作全新的砖块,而是使用已有的砖块。
有些砖块用来砌墙,有些做成窗户,还有些用于搭建屋顶。
通过组合这些可重复使用的砖块,就能建造出无数不同的建筑。
React 组件的运作方式完全相同。
同一个 Button 组件可能会出现在:
- 登录页面
- 模态窗口内
- 结账页面
- 导航栏中
你只需创建一次即可。
然后将其放在需要的地方即可。
这正是组件带来的真正价值。
React 组件模型的设计理念
React 采用组件模式,是因为它们能够解决实际存在的痛点。
1. 可重用性
只需构建一次。
便可无限次重复使用。
无需为同一个按钮代码重复编写二十次,只需定义一个 Button 组件,然后在应用的任何需要位置使用它即可。
2. 可读性
让我们对比两种情况。
一个长达 2,000 行的文件。
与……
二十个各自功能明确的独立文件。
六个月后您更愿意回到哪种代码结构中?
较小的组件显然更易于理解。
3. 可维护性
想象一下,您的公司决定更改主按钮的颜色。
如果您没有将用户界面拆分为组件,那么这个改动就意味着需要查找并编辑数十个文件。
但有了可复用的按钮组件,只需在一个地方进行修改即可。
使用该按钮的每个界面都会立即反映出更新结果。
4. 团队协作
想象有五名开发者负责同一个代码库。
一人负责导航栏。
另一人负责首页区域。
第三人负责制作产品卡片。
第四人负责页脚部分。
第五名开发者的任务则是将所有这些部分整合在一起。
由于每个功能都存在于独立的组件中,因此无需干扰他人的工作,也不必等待某个文件可用。
正是这种并行工作流程,使得组件在现实世界的开发团队中显得如此重要。
函数式组件
如今的 React 代码库几乎完全依赖于函数式组件。
从本质上讲,函数式组件不过是一个返回 JSX 的 JavaScript 函数而已。
以下是最基本的实现版本:
function Welcome() {
return <h1>Hello, React!</h1>;
}
乍看之下,它就像一个普通的 JavaScript 函数——因为它确实如此。
它的独特之处在于,它不会返回数字或字符串之类的值,而是返回 JSX,而 React 会利用这些 JSX 来决定在屏幕上渲染什么内容。
让我们逐部分来分析:
function Welcome()
这里我们声明了一个名为 Welcome 的函数。
请注意函数名开头的大写 “W”。
React 会专门检测首字母是否为大写,以此判断某个函数应被视为组件。
接下来是这一行代码:
return <h1>Hello, React!</h1>;
该函数的任务是返回 JSX。
因此每当 React 渲染 Welcome 时,就会显示这个标题。
就是这么简单。
你刚刚创建了第一个组件。
创建你的第一个组件
当项目规模逐渐扩大时,开发者通常会为每个组件单独创建一个文件。
典型的文件夹结构可能如下所示:
src
├── App.jsx
└── components
└── Welcome.jsx
Welcome.jsx 文件的内容如下:
function Welcome() {
return <h1>Welcome to React!</h1>;
}
export default Welcome;
将组件拆分到独立的文件中,能让代码库保持整洁,且在项目规模扩大时更易于浏览。
导出组件
你或许会对这一行的作用感到好奇:
export default Welcome;
假设你刚刚编写了一个功能完善、可重复使用的组件。
只要它存在于自己的文件中,应用中的其他部分就无法访问它。
通过导出功能,才能让该组件在其他地方被使用。
这有点像发表手稿——一旦手稿公之于众,任何人都可以获取并阅读它。
这里的逻辑也是如此——一旦导出了组件,项目中的其他文件就可以导入它并加以使用。
还有其他导出组件的方法,我们将在本系列的后续部分介绍,但刚开始使用时 export default 是最常用的选择。
导入组件
让我们把 Welcome 导入到 App.jsx 中并加以使用。
import Welcome from "./components/Welcome";
这一行实际上是在向 React 下达指令:
“请从这个文件中获取
Welcome组件,这样我就可以在这里直接使用了。”
一旦导入该组件,渲染它几乎毫不费力:
function App() {
return (
<>
<Welcome />
</>
);
}
仔细看看这段语法:
<Welcome />
尽管 Welcome 最初只是个普通的 JavaScript 函数,但我们仍能像使用原生 HTML 标签一样来使用它。
这正是使用 React 时最优雅的特点之一——用户自定义的函数可以变成界面中可重复使用的构建模块。
React 如何看待组件
当 React 遇到这一行代码时:
<Welcome />
它并不会将其视为标记语言。
实际上,其内部处理过程更像是这样:
Call the Welcome() function
↓
Receive JSX
↓
Convert JSX
↓
Update the Virtual DOM
↓
Render the UI
简而言之,每个组件归根结底都是一个函数调用,该调用会返回界面的一部分内容。
一旦理解了这个原理,组件就不再显得像是某种神奇的魔法了。
命名规则
有一些值得牢记的命名规范。
合适的名称:
- Navbar
- Footer
- Hero
- ProductCard
- UserProfile
应避免使用的名称:
- navbar
- footer
- component
- abc
这样做的原因是什么?
React 依靠大小写来区分用户自定义的组件与内置的 HTML 标签。
看这个例子:
<Navbar />
React 会将其视为对用户自定义组件的引用。
再对比这个:
<div>
React 会将其解释为标准的、内置的 HTML 元素。
选择清晰、具有描述性的名称,也能在后续有其他开发者需要阅读和理解你的代码时带来便利。
核心要点
以下是对目前所学内容的简要总结。
- 组件是独立且可重复使用的用户界面单元。
- 构建 React 应用实际上就是将各个组件组合在一起。
- 函数式组件是返回 JSX 的普通 JavaScript 函数。
- 将应用拆分为组件可以提高可读性、可重用性以及长期维护性。
- 设计良好的组件会专注于完成单一功能。
- 通常的做法是将每个组件放在单独的文件中,并在需要时导入使用。
- 大写规则是 React 区分自定义组件与普通 HTML 元素的方式。
相关阅读
- 构建 React 的思维模型:状态同步、状态与钩子 — 了解 React 核心概念——状态同步、组件、属性、状态及钩子——背后的原理,从而培养直觉而非死记硬背 API。
- 利用 React 条件渲染处理现实世界的 UI 状态 — 通过实用的条件渲染模式,学习如何在 React 中实现身份验证、角色权限、加载状态、错误提示以及空状态等 UI 功能。
catch () 会抛出 SyntaxError —— 了解为何空的 catch 参数列表会导致 JavaScript 解析彻底失败,并查看两种语法正确的无参数 catch 块写法。