3、React核心概念:JSX语法、组件化思想、函数组件与类组件、组件的挂载与渲染
好,咱们进入第三章。这一章可以说是React的「地基」。
你想想看,不管以后你用React写多复杂的项目,最终都绕不开这几个概念:JSX怎么写、组件怎么拆、函数组件和类组件选哪个、组件又是怎么跑到页面上的。
我个人习惯,每次带新人时,都会先让他们把这章吃透。因为很多坑,其实都是基础概念没搞明白埋下的。
3.1 JSX语法:为什么在JavaScript里写HTML?
我第一次看到JSX时,心里也犯嘀咕:「这什么玩意儿?HTML和JS混在一起,不乱吗?」
但用了一段时间后,我承认——真香。
JSX是什么?
JSX是JavaScript的语法扩展。它长得像HTML,但本质是JS。React用它来描述UI结构。
const element = <h1>Hello, React!</h1>;
你看,这行代码既不是纯HTML,也不是纯JS。但它能跑。因为React会通过Babel把它编译成 React.createElement() 调用。
核心要点:JSX最终会被编译成普通的JavaScript函数调用。所以JSX里可以写任何JS表达式。
JSX的规则,记住这几点就够了:
- 只能有一个根元素——可以用
<></>空标签包裹 - 属性用驼峰命名——比如
className、onClick - 花括号里写JS表达式——比如
{变量}、{函数调用()} - 条件渲染用三元运算符——比如
{isLogin ? <User /> : <Guest />}
我的小技巧:写JSX时,我习惯把逻辑尽量抽到外面。JSX里只保留简单的三元判断或map循环。太复杂的逻辑放外面,代码会清爽很多。
3.2 组件化思想:把页面拆成积木
说白了,组件化就是把一个页面拆成一个个独立的小块。每个小块只管自己的事。
我在项目中遇到过最典型的反例:一个页面文件写了2000行代码,改一个按钮要滚动半天。后来重构时,我把它拆成了十几个小组件,每个组件不超过100行。维护起来舒服多了。
为什么要组件化?
- 复用——写一次,到处用
- 隔离——改A组件,不影响B组件
- 可测试——每个组件可以单独测
- 好理解——看一眼组件名,就知道它干嘛的
你想想看,一个页面就像一栋楼。组件就是砖块、门窗、水管。每个部件独立生产,最后组装起来。出了问题,换那块砖就行,不用拆楼。
3.3 函数组件 vs 类组件:我该用哪个?
这个问题,几乎每个初学者都会问。我直接说结论:现在优先用函数组件 + Hooks。
但类组件你也要懂。因为很多老项目还在用,面试也常考。
函数组件长这样:
function Welcome(props) {
return <h1>你好,{props.name}</h1>;
}
简单、直接。就是一个接收props、返回JSX的函数。
类组件长这样:
class Welcome extends React.Component {
render() {
return <h1>你好,{this.props.name}</h1>;
}
}
类组件必须继承 React.Component,而且必须实现 render() 方法。
| 对比项 | 函数组件 | 类组件 |
|---|---|---|
| 写法 | 简洁,就是一个函数 | 啰嗦,要继承、要写render |
| 状态管理 | 用 useState Hook |
用 this.state + setState |
| 生命周期 | 用 useEffect 模拟 |
有专门的声明周期方法 |
| this指向 | 不需要关心 | 要手动绑定或使用箭头函数 |
| 性能 | 通常更轻量 | 实例化开销稍大 |
注意:我曾经在一个项目里混用了函数组件和类组件,结果团队成员经常搞混this的绑定方式。后来统一改成函数组件,问题就没了。所以我的建议是——新项目统一用函数组件。
3.4 组件的挂载与渲染:组件是怎么跑到页面上的?
嗯,这里要注意。很多新手以为写了组件,它就会自动显示。其实不是的。
挂载(Mount),就是把组件插入到真实DOM中的过程。
React里,一切从 ReactDOM.createRoot() 开始:
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
这段代码做了三件事:
- 找到HTML里id为
root的DOM节点 - 创建一个React根容器
- 把
<App />组件渲染进去
渲染过程,简单来说是这样的:
- React调用组件的函数(或类组件的render方法)
- 得到虚拟DOM(Virtual DOM)树
- 对比上一次的虚拟DOM(Diff算法)
- 计算出最小的DOM操作
- 更新真实DOM
说白了,React不是直接操作DOM的。它先在内存里算好「最优方案」,再一次性更新。这也是它快的原因。
我的经验:刚开始学React时,别纠结虚拟DOM的细节。你只要记住——React帮你做了DOM操作的优化。你只管写组件,它负责高效更新。
组件的生命周期(函数组件版):
用 useEffect 可以模拟类组件的生命周期:
import { useEffect } from 'react';
function MyComponent() {
// 组件挂载时执行一次
useEffect(() => {
console.log('组件挂载了');
// 组件卸载时执行
return () => {
console.log('组件卸载了');
};
}, []);
// 依赖项变化时执行
useEffect(() => {
console.log('count变了');
}, [count]);
return <div>Hello</div>;
}
你看,useEffect 的第二个参数是依赖数组。空数组表示只在挂载时执行一次。有依赖项时,依赖变了就执行。返回的函数在卸载时执行。
记住这个规律:
useEffect(() => {}, [])→ 相当于componentDidMountuseEffect(() => {}, [dep])→ 相当于componentDidUpdateuseEffect(() => { return () => {} }, [])→ 相当于componentWillUnmount
好了,这一章的内容就这些。JSX语法、组件化思想、函数组件与类组件的选择、组件的挂载与渲染——这四个概念,是React的基石。你把这章吃透了,后面学状态管理、路由、Hooks都会轻松很多。
下一章,咱们聊聊React的状态管理和事件处理。到时候我会分享一些我在实际项目中踩过的坑,保证有用。