React 核心概念:JSX 语法、虚拟 DOM、组件化思想、单向数据流
大家好,我是你们的前端老司机。今天咱们来聊聊 React 的四个核心概念。
说实话,这四个东西你搞懂了,React 就算入门了。我当年刚学的时候,也是被这些概念绕得晕头转向。后来在项目里摔了几次跤,才真正明白它们的设计意图。
1. JSX 语法:JavaScript 的 HTML 扩展
JSX 是什么?说白了,就是让你在 JavaScript 里写 HTML。
你想想看,以前我们写前端,HTML 是 HTML,JS 是 JS,两个文件来回切。React 觉得这样太麻烦了,干脆把模板和逻辑揉在一起。
核心认知:JSX 不是模板引擎,它是 JavaScript 的语法糖。
来看个最简单的例子:
const element = <h1>Hello, World!</h1>;
这段代码,浏览器是看不懂的。它需要被 Babel 编译成:
const element = React.createElement('h1', null, 'Hello, World!');
嗯,这里要注意。JSX 里写表达式要用花括号 {},不是双花括号 {{}}。双花括号那是 Vue 的写法,我见过不少新手搞混。
const name = '张三';
const element = <p>你好,{name}</p>;
个人习惯:我写 JSX 时,如果属性值是个字符串,就用双引号;如果是表达式,就用花括号。这样一眼就能看出哪些是静态的,哪些是动态的。
JSX 还有一些规则:
- 必须有一个根元素,或者用
<></>空标签包裹 - 标签必须闭合,自闭合标签要写成
<br /> - class 要写成 className,因为 class 是 JavaScript 的保留字
- for 要写成 htmlFor
我曾经踩过的坑:有一次在项目里用 JSX 渲染列表,忘记给每个元素加 key 属性。结果列表更新时,整个列表都重新渲染了,性能直接崩了。key 属性一定要加,而且要用唯一且稳定的值。
2. 虚拟 DOM:性能优化的秘密武器
虚拟 DOM 是什么?就是一个轻量级的 JavaScript 对象,它是对真实 DOM 的抽象。
为什么会需要这个东西?因为直接操作真实 DOM 太慢了。你想想看,每次修改 DOM,浏览器都要重新计算样式、布局、绘制,这一套流程下来,性能开销很大。
React 的做法是:
- 数据变化时,先在虚拟 DOM 上做修改
- 然后比较新旧两个虚拟 DOM 的差异(Diff 算法)
- 最后只把差异部分更新到真实 DOM 上
这个过程叫「协调」(Reconciliation)。
核心认知:虚拟 DOM 不是 React 独有的,Vue 也有。但 React 的 Diff 算法有自己的特点,比如同层比较、类型判断等。
我记得有一次做数据大屏项目,每秒要更新上千条数据。如果用 jQuery 直接操作 DOM,页面早就卡死了。但用 React 的虚拟 DOM,性能完全扛得住。
虚拟 DOM 的工作流程:
// 虚拟 DOM 就是一个普通的 JavaScript 对象
const vNode = {
type: 'div',
props: { className: 'container' },
children: [
{ type: 'h1', props: {}, children: '标题' }
]
};
避坑指南:虚拟 DOM 虽然快,但不是万能的。如果你的组件树特别深,或者每个组件都很大,Diff 算法的计算量也会很大。这时候可以考虑用 React.memo 或者 useMemo 来做优化。
3. 组件化思想:把页面拆成积木
组件化,说白了就是把页面拆成一个个独立的小块。每个小块负责自己的逻辑和样式,互不干扰。
我刚开始做前端时,一个页面就是一个大文件,几千行代码,改个样式要找半天。后来用了组件化,真香。
React 里的组件有两种写法:
| 类型 | 写法 | 特点 |
|---|---|---|
| 函数组件 | 用函数定义 | 简洁,推荐使用 |
| 类组件 | 用 class 定义 | 功能完整,但代码冗余 |
来看个函数组件的例子:
function Welcome(props) {
return <h1>你好,{props.name}</h1>;
}
组件化的好处:
- 复用性:写一次,到处用
- 可维护性:每个组件只关心自己的事
- 可测试性:组件独立,容易写单元测试
我曾经犯过的错:刚开始写组件时,总想把所有功能都塞到一个组件里。结果那个组件又大又乱,改一个地方要小心翼翼。后来我学会了「单一职责原则」——一个组件只做一件事。
4. 单向数据流:数据从哪来,到哪去
单向数据流,意思是数据只能从父组件流向子组件。子组件不能直接修改父组件的数据。
你想想看,如果数据可以随便改,那出了问题你都不知道是谁改的。单向数据流让数据的变化变得可预测、可追踪。
数据传递的方式:
- 父组件通过 props 把数据传给子组件
- 子组件通过回调函数通知父组件修改数据
// 父组件
function Parent() {
const [count, setCount] = useState(0);
return (
<Child
count={count}
onIncrement={() => setCount(count + 1)}
/>
);
}
// 子组件
function Child({ count, onIncrement }) {
return (
<div>
<p>计数:{count}</p>
<button onClick={onIncrement}>增加</button>
</div>
);
}
核心认知:单向数据流不是 React 的发明,它是一种设计模式。但 React 把它贯彻得很彻底。
单向数据流的优点:
- 可预测:数据变化有迹可循
- 易调试:出问题能快速定位
- 性能好:数据变化范围可控
个人经验:在项目中,我习惯把共享数据放在最近的公共父组件里。如果数据需要在多个不相关的组件间共享,那就考虑用状态管理库,比如 Redux 或 Zustand。
嗯,这四个概念就讲到这里。你可能会问:「为什么 React 要这么设计?」
其实答案很简单:为了让前端开发更简单、更高效。JSX 让模板和逻辑在一起,虚拟 DOM 让性能更好,组件化让代码更清晰,单向数据流让数据更可控。
下一章,咱们聊聊 React 的生命周期和 Hooks。到时候见。
公众号:蓝海资料掘金营,微信deep3321