React JSX 入门指南:从基础到进阶(五)

React 是目前最流行的前端框架之一,而 JSX 是 React 中用于编写 UI 组件的重要工具。本文将详细介绍 JSX 的基本概念、语法规则、表达式嵌入、条件渲染、列表渲染以及样式处理等内容,帮助你更好地理解和使用 JSX。

什么是 JSX?

JSX(JavaScript XML)是一种类似于 XML 的 JavaScript 语法扩展,它允许你在 JavaScript 代码中使用类似 HTML 的语法来描述 UI 组件。虽然 JSX 看起来像是 HTML,但实际上它会被编译成纯 JavaScript 代码,最终调用 React.createElement 方法。

使用 JSX 的主要优势包括:

  • 执行高效:编译后的代码经过优化,运行速度更快。
  • 类型安全:编译阶段可以发现错误,尤其是在与 TypeScript 结合使用时。
  • 编写便捷:UI 结构直观清晰,嵌入 JavaScript 表达式更加灵活,编写模板简单快速。
  • 本质特性:JSX 不是字符串或 HTML,而是会被 Babel(Vite 内置)编译成 React 元素。

下面是一个简单的 JSX 示例:

const element = 
<h1>Hello, world!</h1>;

这段代码看起来可能有些奇怪,但它并不是字符串或 HTML,而是 JSX 语法。JSX 会被编译成如下 JavaScript 代码:

const element = React.createElement('h1', null, 'Hello, world!');

渲染 React 元素

React 元素是构成 React 应用的最小单位。与浏览器的 DOM 元素不同,React 元素实际上是普通的 JavaScript 对象。React DOM 会确保浏览器 DOM 的数据内容与 React 元素保持一致。

要将 React 元素渲染到页面上,可以使用 ReactDOM.render 方法。以下是一个完整的示例:

const element = <h1 className="foo">Hello, world</h1>;
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(element);

在这个例子中,我们创建了一个 React 元素 element,并将其渲染到具有 id 为 root 的 DOM 节点中。

JSX 语法规则

虽然 JSX 看起来像 HTML,但有一些严格的规则需要遵循:

1. 必须闭合标签

  • 自闭合标签:HTML 中可以使用 <br>,但在 JSX 中必须使用 <br />。
  • 所有标签都要闭合:例如 <div></div>。

2. class → className

由于 class 是 JavaScript 的关键字,因此在 JSX 中使用 className 代替 class。

<div className="container">内容</div>

3. for → htmlFor

在 HTML 中,<label> 标签的 for 属性用于关联表单控件。在 JSX 中,应使用 htmlFor 代替 for。

<label htmlFor="id">标签文本</label>

4. 自定义组件必须大写开头

自定义组件的名称必须以大写字母开头,否则会被当作 HTML 标签处理。

<Card />  {/* 正确,自定义组件 */}
<card />  {/* 错误,会被当作 <card> HTML 标签 */}

5. 注释

在 JSX 中,注释需要写在花括号 {/ 注释内容 /} 中。

jsx{/* 这是一个 JSX 注释 */}

6. 根元素

return 语句中只能有一个根节点。如果需要返回多个元素,可以使用片段 <> 或 <Fragment>。

return (
  <>  {/* 碎片 Fragment,空标签,不渲染 DOM */}

<h1>标题</h1>

<p>段落</p>
  </>
);

表达式嵌入

JSX 最强大的功能之一是可以在花括号 {} 中嵌入 JavaScript 表达式。这些表达式可以是任何有效的 JavaScript 代码,但不能是语句(如 if 或 for)。

1. 基本表达式

任何有效的 JavaScript 表达式都可以嵌入到 JSX 中:

const name = 'runoob';
const now = new Date().toLocaleString();

return (

<div>

<h1>你好,{name}!</h1>

<p>当前时间:{now}</p>

<p>计算结果:{2 + 3 * 5}</p>  {/* 17 */}
  </div>
);

2. 条件渲染

可以使用三元运算符或逻辑与 && 进行条件渲染:

const isLoggedIn = true;
const count = 0;

return (

<div>
    {isLoggedIn ? 
<h1>欢迎回来,{name}!</h1> : <h1>请登录</h1>}

    {count > 0 && 
<p>你有 {count} 条未读消息</p>}  {/* count 为 0 时不渲染 */}
  </div>
);

3. 列表渲染

使用 map() 方法可以渲染数组中的元素。为了提高性能,每个元素必须有一个唯一的 key 属性。

const items = [
  { id: 1, name: '苹果' },
  { id: 2, name: '香蕉' },
  { id: 3, name: '橙子' },
];

return (

<ul>
    {items.map(item => (
      <li key={item.id}>  {/* key 必须唯一且稳定! */}
        {item.name}
      </li>
    ))}
  </ul>
);

key 的重要性

  • 没有 key:React 会发出警告,可能导致渲染错误,尤其是在列表动态变化时。

  • 坏习惯:用索引作为 key(key={index})——当列表顺序变化时,会导致不必要的重渲染或状态丢失。

  • 最佳实践:使用数据中的唯一 ID(如数据库 id)。

样式处理

React 提供了多种方式来处理样式,这里介绍两种最基础的方法:内联样式和 CSS Modules。

1. 内联样式

使用 style 属性,值是一个对象(驼峰命名):

return (
  <div
    style={{
      backgroundColor: '#f0f0f0',
      padding: '20px',
      borderRadius: '8px',
      textAlign: 'center',
      fontFamily: 'Arial, sans-serif',
    }}
  >
    <h2 style={{ color: 'blue', marginBottom: '10px' }}>
      内联样式示例
    </h2>
  </div>
);
  • 优点:动态样式容易实现(可以用变量)。
  • 缺点:不适合复杂的样式管理。

2. CSS Modules(推荐,作用域隔离)

CSS Modules 是一种 CSS 文件,其中类名和动画名默认是局部作用域的。这有助于避免全局样式冲突。

创建一个 CSS 文件,例如 Card.module.css:

/* Card.module.css */
.card {
  background: white;
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.1);
  padding: 20px;
  margin: 20px;
}

.title {
  color: #333;
  margin: 0 0 10px 0;
}

.content {
  color: #666;
}

在组件中导入并使用:

import styles from './Card.module.css';

const Card = ({ title, content, imageUrl }) => {
  return (
    <div className={styles.card}>
      <h3 className={styles.title}>{title}</h3>
      <p className={styles.content}>{content}</p>
    </div>
  );
};

export default Card;
  • 优点:类名自动哈希(如 .card__abc123),不会冲突。

实践示例

1. 基本 JSX 示例

const element = <h1 className="foo">Hello, world</h1>;
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(element);

2. 多个元素

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(

<div>

<h1>菜鸟教程</h1>

<h2>欢迎学习 React</h2>
    <p data-myattribute="somevalue">这是一个很不错的 JavaScript 库!</p>
  </div>
);

3. 独立文件

将 JSX 代码放在一个独立文件中,例如 helloworld_react.js:

const element = <h1 className="foo">Hello, world</h1>;
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(element);

在 HTML 文件中引入该 JS 文件:


<body>
  <div id="example"></div>
  <script type="text/babel" src="helloworld_react.js"></script>
</body>

4. 表达式嵌入

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(

<div>

<h1>{1 + 1}</h1>
  </div>
);

5. 条件渲染

let i = 1;
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(

<div>

<h1>{i == 1 ? 'True!' : 'False'}</h1>
  </div>
);

6. 内联样式

const myStyle = {
  fontSize: 100,
  color: '#FF0000'
};

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <h1 style={myStyle}>菜鸟教程</h1>
);

7. 注释

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(

<div>

<h1>菜鸟教程</h1>
    {/*
      注释...
    */}
  </div>
);

8. 数组

const arr = [

<h1>菜鸟教程</h1>,

<h2>学的不仅是技术,更是梦想!</h2>,
];

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(

<div>
    {arr}
  </div>
);

总结

通过本文,我们详细介绍了 React JSX 的基本概念、语法规则、表达式嵌入、条件渲染、列表渲染以及样式处理等内容。希望这些知识能帮助你更好地理解和使用 JSX,从而提升你的 React 开发技能。如果你有任何疑问或建议,欢迎在评论区留言交流。