一、组件化思维入门:什么是组件化、为什么需要组件化、React组件的基本概念、从HTML到JSX的思维转变

1.1 什么是组件化?说白了就是搭积木

我记得刚入行那会儿,写前端页面就是一把梭——HTML、CSS、JavaScript全揉在一个文件里。一个页面几千行代码,改个按钮颜色得翻半天。后来接触了组件化,才恍然大悟:这不就是搭积木吗?

组件化,就是把页面拆成一个个独立、可复用的小块。每个小块只管自己的事,互不干扰。比如一个搜索框,它自己管自己的样式、交互、数据。你把它往页面上一放,它就能工作。

核心要点:组件 = 结构 + 样式 + 行为 的封装体

举个例子,一个典型的页面可以拆成这样:

页面
├── 头部导航(Header)
│   ├── Logo
│   ├── 导航菜单(NavMenu)
│   └── 用户信息(UserInfo)
├── 内容区(Content)
│   ├── 文章列表(ArticleList)
│   │   └── 文章卡片(ArticleCard)
│   └── 侧边栏(Sidebar)
│       ├── 搜索框(SearchBox)
│       └── 标签云(TagCloud)
└── 底部(Footer)

你看,每个部分都是独立的组件。它们可以单独开发、单独测试、单独维护。这就是组件化的核心思想。

1.2 为什么需要组件化?我踩过的坑告诉你

说实话,我刚做React时也觉得组件化麻烦。一个简单的按钮,非得拆成组件,写一堆props,图啥?直到我在项目中遇到了这些事:

  • 改一处,崩一片:一个全局的CSS类名,改了个颜色,结果三个页面样式全乱了
  • 代码复制粘贴:同样的表单校验逻辑,在五个页面里各写了一遍,后来要改校验规则,得改五个地方
  • 新人上手慢:一个页面几千行代码,新同事看了一周都不敢动

组件化能解决这些问题,原因有三:

痛点 组件化方案
样式冲突 组件内样式隔离,互不影响
重复代码 组件复用,一处修改处处生效
维护困难 组件职责单一,易于理解和修改

我的经验:组件化不是银弹。别为了组件化而组件化。如果一个组件只在一个地方用一次,而且逻辑简单,那写成内联代码也没问题。我见过有人把一行文本都拆成组件,那就过度设计了。

1.3 React组件的基本概念

React里的组件,本质上就是一个函数或一个类。它接收输入(props),返回输出(JSX)。就这么简单。

来看两种最常见的组件写法:

函数组件(推荐)

// 函数组件:就是一个普通的JavaScript函数
function Greeting(props) {
  return <h1>你好,{props.name}!</h1>;
}

// 使用组件
<Greeting name="张三" />

类组件(历史遗留)

// 类组件:继承React.Component
class Greeting extends React.Component {
  render() {
    return <h1>你好,{this.props.name}!</h1>;
  }
}

注意:现在新项目基本都用函数组件了。类组件你了解就行,面试可能会问,但实际开发中我建议直接用函数组件 + Hooks。我曾经接手过一个全是类组件的项目,那代码量...嗯,你懂的。

组件有三个核心概念:

  • Props:组件的输入参数,由父组件传递,子组件不能修改
  • State:组件的内部状态,可以改变,改变后组件会重新渲染
  • 生命周期:组件从创建到销毁的过程(函数组件用Hooks模拟)

1.4 从HTML到JSX的思维转变

这是很多初学者最不适应的地方。你想想看,写了那么多年HTML,突然告诉你「以后在JavaScript里写HTML」,是不是觉得怪怪的?

我第一次看到JSX时,心里想的是:「这什么玩意儿?HTML和JS混在一起,不违背关注点分离原则吗?」

后来我才明白,React的哲学是:关注点分离不是技术分离,而是职责分离。一个组件同时包含它的结构和行为,这才是真正的「关注点在一起」。

HTML vs JSX 的差异

HTML JSX
class="xxx" className="xxx"
for="xxx" htmlFor="xxx"
style="color: red" style={ { color: 'red' } }
onclick="handleClick()" onClick={handleClick}
单标签必须闭合 所有标签必须闭合:<br />
可以写注释 <!-- --> 必须用JS注释 {/* */}

思维转变的关键:把HTML看作JavaScript的扩展,而不是独立的模板语言。JSX最终会被编译成React.createElement()调用,本质上就是JavaScript。

来看一个完整的例子,感受一下从HTML到JSX的转变:

// HTML写法
<div class="user-card">
  <img src="avatar.jpg" class="avatar" />
  <h2>张三</h2>
  <p class="bio">前端工程师</p>
  <button onclick="follow()">关注</button>
</div>

// JSX写法
function UserCard() {
  const [isFollowed, setIsFollowed] = useState(false);
  
  return (
    <div className="user-card">
      <img src="avatar.jpg" className="avatar" />
      <h2>张三</h2>
      <p className="bio">前端工程师</p>
      <button onClick={() => setIsFollowed(!isFollowed)}>
        {isFollowed ? '已关注' : '关注'}
      </button>
    </div>
  );
}

你发现没?JSX里可以直接写JavaScript表达式(用花括号包裹),可以绑定事件,可以控制状态。这就是组件化的威力——结构、样式、行为,全在一个组件里,高内聚、低耦合

避坑指南:我曾经在JSX里写if语句,结果报错了。记住,JSX里只能写表达式,不能写语句。要用条件渲染,请用三元运算符或逻辑与:

// 正确
{isLoggedIn ? <UserPanel /> : <LoginButton />}
{isAdmin && <AdminPanel />}

// 错误
{if (isLoggedIn) { return <UserPanel /> }}

小结

这一章我们聊了:

  • 组件化就是搭积木,把页面拆成独立的小块
  • 组件化能解决样式冲突、代码重复、维护困难三大痛点
  • React组件就是函数或类,接收props返回JSX
  • JSX是HTML的JavaScript化,记住那几个差异点就行

下一章,我们会深入组件的核心——Props和State。到时候我会分享一个我踩过的坑,关于state更新不及时导致线上bug的...嗯,那故事挺有意思的。