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 的做法是:

  1. 数据变化时,先在虚拟 DOM 上做修改
  2. 然后比较新旧两个虚拟 DOM 的差异(Diff 算法)
  3. 最后只把差异部分更新到真实 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