组件、状态、列表、条件渲染:一篇文章入门 React JSX

54 阅读4分钟

第一次接触 React 时,可能会被 JSX 函数组件 状态管理这些概念绕晕。其实,只要抓住一个简单的例子,把里面的细节拆开来看,你会发现这些概念非常自然。

下面就通过一个小小的根组件示例,来系统梳理:

  • 函数组件是什么、为什么适合做组件
  • JSX 的本质是什么
  • useState 如何管理组件状态
  • 列表渲染、条件渲染怎么写
  • 事件处理和交互逻辑如何组织

前言

JSX 是 JavaScript XML 的缩写,是 React 引入的语法扩展(并非新语言),允许你在 JavaScript 代码中直接书写类似 HTML 的标记语法,用于描述 React 组件的 UI 结构。

简单来说:JSX = JavaScript + HTML 语法糖,它不是直接运行在浏览器中的,会被 Babel 等工具编译为标准的 JavaScript 代码(React.createElement 调用),最终生成 React 能识别的虚拟 DOM

一、组件:用函数组合 JS / HTML / CSS

// useState -> React 的核心 Hook,相当于 vue 中的ref
// createElement -> 创建虚拟 DOM 的函数,JSX 最终会被编译为 createElement 调用
import { useState , createElement} from 'react';
// 导入组件的样式文件,实现样式隔离。
import './App.css';

在这个示例里,根组件本质上就是一个普通的 JavaScript 函数:

function RootComponent() {
  // 一些状态和逻辑
  return (
    <>
      {/* 一些 JSX UI */}
    </>
  );
}

几个关键点:

  • 组件是函数
    输入是 props 和内部状态,输出是 UI 描述(JSX)。
    函数天然适合做组件:

    1、 有清晰输入输出

    2、 容易复用

    3、 易于拆分和组合成组件树

  • 组件是 JS / HTML / CSS 的组合

    1、 JS:状态、计算逻辑、事件处理

    2、 HTML:通过 JSX 写结构

    3、 CSS:通过类名和样式文件控制样式

这个示例组件就把“问候语”“待办清单”“登录状态”等 UI 和业务逻辑,都放在一个函数体里组织,非常直观。

二、JSX:语法糖背后还是 createElement

const element = <h2>故事的小黄花,从出生那年就飘着</h2>;
const element2 = createElement('h2', null, '故事的小黄花,从出生那年就飘着');

这两行是等价的,说明了几点:

  • JSX 是语法糖

    • <h2>...</h2> 会在编译阶段被转换成 createElement('h2', ...)
    • JSX 只是让我们写 UI 更接近 HTML,提升可读性和开发效率
  • “XML in JS”
    本质是在 JS 里写一种“类似 XML 的结构描述”,最终都是 JS 对象。

  • 类名用 className
    在 JSX 中不能写 class="title",因为 class 是 JS 关键字,要写成 className="title"

    <span className="title">{name}</span>
    

三、useState:React 版 “ref”

组件中用了三个状态:

const [name, setName] = useState('杰伦');
const [todos, setTodos] = useState([
  { id: 1, title: '晴天', done: false },
  { id: 2, title: '稻香', done: false },
]);
const [isLoggedIn, setIsLoggedIn] = useState(false);

理解这段解构代码,只需要记住一句话:

useState 返回一个数组:
第一个是当前状态值,第二个是更新状态的函数。

这和 Vue 里的 ref 很像:都用来维护某个“响应式值”。

1. 状态驱动 UI

在代码中:

  • name 控制问候语中的歌手名字
  • todos 控制待办列表的渲染
  • isLoggedIn 控制“已登录 / 未登录”提示和按钮文案

每次调用对应的 setXxx,React 会触发一次重新渲染,UI 自动更新。

2. 状态的异步更新例子

组件里有这样一段逻辑:

setTimeout(() => {
  setName('Jay Chou');
}, 3000);

含义是:组件渲染后 3 秒,把 name 从“杰伦”改成 “Jay Chou”,UI 随之更新。

真实项目中,更推荐把这种副作用放进 useEffect,但作为演示:
它很直观地展示了“修改状态 → 触发重渲染 → UI 自动变化”的流程。

四、列表渲染:用 map 生成节点

代码中的待办列表通过 map 来渲染:

todos.length > 0 ? (
  <ul>
    {todos.map(todo => (
      <li key={todo.id}>
        {todo.title}
      </li>
    ))}
  </ul>
) : (
  <div>暂无待办事项</div>
)

可以总结几个实战要点:

  • 用 map 生成列表
    数组里的每一项,映射成一个 JSX 节点,非常自然。
  • key 必须写
    key={todo.id} 帮助 React 高效地识别每个列表项,避免不必要的 DOM 操作。
  • 和条件渲染结合
    todos.length > 0 ? ... : ...
    有内容就显示列表,没有内容就显示“暂无待办事项”。

五、条件渲染:三元表达式写 UI 分支

除了列表,组件还通过条件渲染来展示登录状态:

{isLoggedIn ? <div>已登录</div> : <div>未登录</div>}

搭配按钮文本:

<button onClick={toggleLogin}>
  {isLoggedIn ? '退出登录' : '登录'}
</button>

onClick={toggleLogin} 是 React 的事件绑定方式,和原生 JavaScriptVue 的事件绑定在语法形式、底层实现、事件机制上都有明显区别。

在 React 的JSX 中绑定事件时,必须使用驼峰命名(比如 onClickonChangeonMouseEnter

六、事件处理:把交互逻辑写成函数

登录状态的切换逻辑被抽成了一个函数:

const toggleLogin = () => {
  setIsLoggedIn(!isLoggedIn);
};

然后绑定到按钮的 onClick 上:

<button onClick={toggleLogin}>
  {isLoggedIn ? '退出登录' : '登录'}
</button>

image.png