CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
React 核心/课时/JSX 与渲染
RawBlame
课时目录14 节

React 核心

  1. 01React 是什么
  2. 02JSX 与渲染
  3. 03函数组件
  4. 04Props 与 State
  5. 05事件处理
  6. 06条件渲染与列表
  7. 07useEffect
  8. 08useRef 与 DOM
  9. 09useMemo、useCallback 与自定义 Hook
  10. 10表单与受控组件
  11. 11Context 共享状态
  12. 12React Router 入门
  13. 13数据获取与错误边界
  14. 14综合练习与 Next.js 方向

JSX 与渲染

JSX 语法、表达式、根元素与 Fragment。

30 分钟

JSX 与渲染

这一课你将能做到

  1. 认出 JSX,并知道它最终还是 JavaScript
  2. 正确使用 className、{} 插入表达式
  3. 给列表每一项写上稳定的 key(并知道为什么)

为什么要学

React 组件要返回「界面长什么样」。
用 JSX 写起来像 HTML,但其实是 JS 语法扩展,构建工具会把它编译成函数调用。

人话:你在 JS 文件里写长得像标签的东西,方便描述界面;浏览器真正执行的仍是 JS。

常见卡点:把 JSX 当成「另一个 HTML 文件」,结果在里面写 class、忘记最外层只能有一个根、把整个对象丢进 {user}。本站卡片标题、进度数字,全是 JSX 里用 {} 插进去的。

先建立图像

const title = "题库";
const el = <h1 className="title">{title}</h1>;

人话拆开看:

  • 外表像标签 <h1>...</h1>
  • {title} 是插入 JS 表达式(这里是变量)
  • className 对应 HTML 的 class(因为 class 在 JS 里是关键字,不能当属性名随便用)

编译后的直觉(不必手写):大约变成 createElement("h1", { className: "title" }, title)。所以 JSX 不是魔法 HTML,是糖衣。

跟着做

步骤 1:根节点(最常见语法报错)

JSX return 时,最外层需要一个根,或用空标签 Fragment:

// 可以:隐形包裹,不增加多余 DOM
return (
  <>
    <h1>本站路径</h1>
    <p>前端主线</p>
  </>
);

// 也可以包一层真实 div
return (
  <div>
    <h1>本站路径</h1>
    <p>前端主线</p>
  </div>
);

相邻两个标签并排 return、外面不包,会语法报错。人话:函数一次只能「交回一件东西」;Fragment 就是那件隐形袋子。

步骤 2:表达式与「不能直接渲染对象」

const user = { name: "ada" };

export function Who() {
  // return <p>{user}</p>;  // 报错:对象不能当 React 孩子
  return <p>{user.name}</p>; // 正确:渲染字符串
}

规则记三条:

  • {} 里放表达式(变量、三元、函数调用),不能直接放 if 语句
  • 布尔值 true/false、null、undefined 通常什么都不显示
  • 数字 0 要小心:条件渲染课会讲 {0 && <X />} 会把 0 画出来

步骤 3:列表与 key(本站课时列表就是这个)

const lessons = [
  { id: 1, title: "HTML" },
  { id: 2, title: "CSS" },
];

export function LessonTitles() {
  return (
    <ul>
      {lessons.map((item) => (
        <li key={item.id}>{item.title}</li>
      ))}
    </ul>
  );
}

key 人话:帮 React 认出「哪一项是哪一项」,好做增删、重排时的更新。
用业务里稳定的 id。列表会插入/删除/排序时:

  • 不要用 Math.random()(每次渲染都变,React 以为全是新项)
  • 慎用纯下标 index(中间插一项,后面的下标全变,容易绑错状态)

步骤 4:属性和样式最小集

function Chip({ active, label }) {
  return (
    <span
      className={active ? "chip on" : "chip"}
      style={{ marginRight: 8 }}
      tabIndex={0}
    >
      {label}
    </span>
  );
}
  • 属性名驼峰:onClick、tabIndex、htmlFor(对应 for)
  • style 是对象,CSS 属性也驼峰:marginRight 不是 margin-right
  • 日常更常用 className 写样式,内联 style 留给动态一两个值

步骤 5:表达式与「不能放对象」

const done = true;
return <p>{done ? "完成" : "未完成"}</p>;
// return <p>{{ a: 1 }}</p>; // 对象不是合法 React 子节点

应看到:{} 里放表达式;原始类型/元素/数组 OK,随意对象会报错。

讲清楚要点

  1. JSX 仍是 JS:文件是 .jsx/.tsx,逻辑用 JS,不要幻想「另一个模板语言无限自由」。
  2. 自定义组件名必须大写开头:<StationCard />;小写 <div>、<span> 当原生标签。
  3. 注释只能写成 {/* 这样 */},不要写 HTML 的 <!-- -->。
  4. 一个表达式一个 {}:{a}{b} 可以;{a + b} 也行。不要写成 {{ a }} 除非你真的要对象(通常不要当孩子)。
  5. 布尔属性:<input disabled={saving} />,不要学 HTML 只写 disabled 却搞不清何时关闭。

你可能会懵的地方

  • 为何不是 class?
    JS 保留字冲突,React 约定 className。写错 class 时有的工具会警告。

  • {} 里能写 if 吗?
    不能直接写语句。先在函数体里用 if 算出 let node = ...,再 {node};或用三元。

  • Fragment <> 是什么?
    不额外生成 DOM 节点的隐形包裹。需要 key 时用 <Fragment key={id}>(从 react 导入)。

  • 为何有时必须 {" "}?
    JSX 里换行空格容易被吃掉;两个元素之间要空格可显式插入。

  • class 为什么写成 className?
    class 是 JS 保留字;SVG 里 strokeWidth 等亦驼峰。

错法对照

错法问题正解
列表不写 key控制台警告、更新错乱稳定 id 作 key
渲染整个对象 {user}运行报错渲染 user.name 等字段
组件名小写 <card />被当成未知 HTML 标签Card 大写
return <h1/><p/> 双根语法错误Fragment 或一个父节点
style="color:red" 字符串不是 HTML 文件style={{ color: "red" }}
多个根又不包 Fragment编译/语法错<>...</> 或单父节点

自测三问

  1. className 和 class 为什么不同?
  2. {title} 里的大括号表示什么?能不能写 if?
  3. key 主要帮 React 解决什么问题?为什么随机数不行?

小结一句话

JSX 用类 HTML 的写法描述 UI,插入数据用 {},列表务必给稳定 key。

动手加深

把一段 createElement 手写与等价 JSX 对照抄一遍,确认 JSX 不是字符串 HTML。

延伸

  • react.dev Describing the UI
  • 下一课:函数组件——把 JSX 装进可复用函数。
加载本节练习…
← 上一课React 是什么下一课 →函数组件