React JSX 语法规则详解与实战指南

99 阅读4分钟

React JSX 语法规则详解与实战指南

一、引言:为什么需要 JSX?

JSX 是 React 的核心语法,它允许我们在 JavaScript 中编写类似 HTML 的结构。与传统的字符串拼接相比,JSX 提供了更直观、更高效的组件化开发方式。本文将从基础语法到实际应用,带你全面掌握 JSX 的规则与技巧。


二、JSX 基础语法规则

1. 基本结构

// 正确写法
const element = <div>Hello, World!</div>;

// 错误写法(缺少 RXH 包裹)
const element = div("Hello, World!");

核心规则

  • 必须用 <> 包裹内容
  • 标签名必须是小写(HTML 标签)或首字母大写(自定义组件)
  • 必须闭合所有标签

2. 嵌套与自闭合标签

// 嵌套结构
const nested = (
  <div>
    <h1>标题</h1>
    <p>段落内容</p >
  </div>
);

// 自闭合标签
const selfClosed = < img src="logo.png" alt="Logo" />;

注意

  • 自闭合标签必须带 /
  • 多个同级元素需用 <>...</> 包裹(Fragment)

3. 表达式与注释

// 插入表达式
const name = "Alice";
const greeting = <h1>Hello, {name}!</h1>;

{/* JSX 注释 */}
const comment = (
  <div>
    内容 {/* 这里是注释 */}
  </div>
);

规则

  • {} 中必须是合法的 JavaScript 表达式
  • HTML 注释在 JSX 中会报错,需用 {/* */} 格式

三、动态内容与事件处理

1. 动态属性与样式

// 动态样式
const isActive = true;
const button = (
  <button style={{ color: isActive ? 'white' : 'black', backgroundColor: isActive ? 'blue' : 'gray' }}>
    Click Me
  </button>
);

// 动态类名(推荐方式)
const className = isActive ? 'active' : 'inactive';
const dynamicClass = <div className={className}>Content</div>;

最佳实践

  • 避免直接写内联样式对象,推荐使用 CSS Modules 或 Styled Components
  • 类名拼接推荐使用 classnames

2. 事件绑定

// 基础事件绑定
function handleClick() {
  alert('Button clicked!');
}
const button = <button onClick={handleClick}>Click</button>;

// 传递参数
const id = 123;
const actionButton = <button onClick={() => handleAction(id)}>Action</button>;

关键点

  • 事件处理函数必须通过 onXXX 属性绑定
  • JSX 中不能直接调用函数,需用事件触发

四、条件渲染与列表渲染

1. 条件渲染

// 三元运算符
const show = true;
const conditional = show ? <div>Visible</div> : null;

// 短路运算符
const shortCircuit = show && <div>Short Circuit</div>;

// 立即执行函数(推荐)
const immediate = (
  <>
    {show && <div>Rendered with IIFE</div>}
  </>
);

2. 列表渲染

// 基础列表
const items = ['Apple', 'Banana', 'Cherry'];
const list = (
  <ul>
    {items.map((item, index) => (
      <li key={index}>{item}</li>
    ))}
  </ul>
);

// 带复杂结构的列表
const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' }
];
const userList = (
  <table>
    <thead>
      <tr>
        <th>ID</th>
        <th>Name</th>
      </tr>
    </thead>
    <tbody>
      {users.map(user => (
        <tr key={user.id}>
          <td>{user.id}</td>
          <td>{user.name}</td>
        </tr>
      ))}
    </tbody>
  </table>
);

关键规则

  • 必须有 key 属性(推荐唯一 ID)
  • 避免在循环中直接返回数组,需用 <>...</> 包裹

五、样式与布局控制

1. 内联样式

const inlineStyle = <div style={{ textAlign: 'center', padding: '20px' }}>
  Centered Content
</div>;

注意事项

  • 样式对象需使用 camelCase(如 fontSize 而非 font-size
  • 优先使用 CSS 类,内联样式仅用于动态场景

2. CSS 模块化

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

const modularCss = (
  <div className={styles.container}>
    <h2 className={styles['title-large']}>Modular CSS</h2>
  </div>
);

六、组件组合与复用

1. 函数组件与 Class 组件

// 函数组件
function Greeting({ name }) {
  return <h1>Hello, {name}!</h1>;
}

// Class 组件
class Counter extends React.Component {
  state = { count: 0 };
  
  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p >
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Increment
        </button>
      </div>
    );
  }
}

2. 组件嵌套

function App() {
  return (
    <div>
      <Greeting name="Alice" />
      <Counter />
    </div>
  );
}

规则

  • 组件首字母必须大写
  • 组件之间可嵌套任意层级

七、Hooks 与 JSX 结合

1. 使用 useState

function TodoApp() {
  const [todos, setTodos] = React.useState(['Buy milk']);
  const [newTodo, setNewTodo] = React.useState('');

  const addTodo = () => {
    setTodos([...todos, newTodo]);
    setNewTodo('');
  };

  return (
    <div>
      <input 
        type="text" 
        value={newTodo} 
        onChange={e => setNewTodo(e.target.value)} 
      />
      <button onClick={addTodo}>Add</button>
      <ul>
        {todos.map((todo, index) => (
          <li key={index}>{todo}</li>
        ))}
      </ul>
    </div>
  );
}

2. 使用 useEffect

function Clock() {
  const [time, setTime] = React.useState(new Date().toLocaleTimeString());

  React.useEffect(() => {
    const timer = setInterval(() => {
      setTime(new Date().toLocaleTimeString());
    }, 1000);
    
    return () => clearInterval(timer); // 清理副作用
  }, []);

  return <h2>Current Time: {time}</h2>;
}

八、性能优化与最佳实践

1. 虚拟 DOM 原理

// 对比直接 DOM 操作
// 不推荐:频繁操作真实 DOM
function updateDOM() {
  const dom = document.getElementById('root');
  dom.innerHTML = 'New Content';
}

// 推荐:使用 React 更新虚拟 DOM
function updateReact() {
  ReactDOM.render(<div>New Content</div>, root);
}

2. 列表渲染优化

// 错误用法(可能导致不必要的重渲)
{items.map((item, index) => (
  <Item key={index} data={item} />
))}

// 正确用法(使用稳定 key)
{items.map(item => (
  <Item key={item.id} data={item} />
))}

核心原则

  • 保证 key 的唯一性
  • 避免使用数组索引作为 key(除非列表不会重新排序)

九、总结与实战建议

  1. 保持简洁:避免过度嵌套,适当使用 Fragment 或第三方库(如 react-fragment)
  2. 类型安全:结合 TypeScript 使用 JSX,获得更好的开发体验
  3. 性能优先:合理使用 memouseCallback 等优化手段
  4. 规范统一:团队约定 JSX 书写风格(如空格、缩进、引号)

十、完整实战示例:待办事项应用

// App.js
import React, { useState } from 'react';
import TodoList from './TodoList';
import TodoInput from './TodoInput';

function App() {
  const [todos, setTodos] = useState([]);
  const [filter, setFilter] = useState('all');

  const addTodo = (text) => {
    setTodos([...todos, { id: Date.now(), text }]);
  };

  const deleteTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };

  return (
    <div className="app">
      <h1>Todo App</h1>
      <TodoInput onAdd={addTodo} />
      <div>
        <button onClick={() => setFilter('all')}>All</button>
        <button onClick={() => setFilter('active')}>Active</button>
        <button onClick={() => setFilter('completed')}>Completed</button>
      </div>
      <TodoList todos={todos} filter={filter} onDelete={deleteTodo} />
    </div>
  );
}

export default App;
// TodoList.js
import React from 'react';

function TodoList({ todos, filter, onDelete }) {
  const filtered = todos.filter(todo => {
    if (filter === 'all') return true;
    if (filter === 'active') return !todo.completed;
    if (filter === 'completed') return todo.completed;
  });

  return (
    <ul>
      {filtered.map(todo => (
        <li key={todo.id}>
          <span 
            className={todo.completed ? 'completed' : ''}
            onClick={() => toggleComplete(todo.id)}
          >
            {todo.text}
          </span>
          <button onClick={() => onDelete(todo.id)}>Delete</button>
        </li>
      ))}
    </ul>
  );
}

export default TodoList;
// TodoInput.js
import React, { useState } from 'react';

function TodoInput({ onAdd }) {
  const [text, setText] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    if (text.trim()) {
      onAdd(text);
      setText('');
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input 
        type="text" 
        value={text} 
        onChange={e => setText(e.target.value)} 
        placeholder="Add a todo..."
      />
      <button type="submit">Add</button>
    </form>
  );
}

export default TodoInput;

运行效果

  • 添加/删除待办事项
  • 按状态过滤任务
  • 点击任务文本标记完成

通过本文的学习,你应该能够熟练掌握 JSX 的核心语法规则,并在实际项目中灵活应用。记住,JSX 的本质是函数调用,理解这一点将帮助你更好地驾驭 React 开发。