JSX语法 #

一、什么是JSX #

JSX(JavaScript XML)是 JavaScript 的语法扩展,允许我们在 JavaScript 中编写类似 HTML 的代码。

1.1 JSX本质 #

javascript
// JSX语法
const element = <h1>Hello, React!</h1>;

// 编译后的JavaScript
const element = React.createElement('h1', null, 'Hello, React!');

1.2 为什么使用JSX #

优势 说明
直观 UI 结构与逻辑放在一起
强大 可使用完整的 JavaScript 能力
类型安全 编译时发现错误
表达力强 支持条件、循环等逻辑

二、JSX基础语法 #

2.1 基本结构 #

javascript
// 单标签
const img = <img src="logo.png" alt="Logo" />;

// 双标签
const div = <div className="container">内容</div>;

// 嵌套结构
const card = (
  <div className="card">
    <h2>标题</h2>
    <p>内容</p>
  </div>
);

2.2 使用括号包裹 #

多行 JSX 使用括号包裹,避免自动插入分号:

javascript
const element = (
  <div>
    <h1>标题</h1>
    <p>内容</p>
  </div>
);

2.3 单个根元素 #

JSX 必须返回单个根元素:

javascript
// ❌ 错误:多个根元素
return (
  <h1>标题</h1>
  <p>内容</p>
);

// ✅ 正确:使用div包裹
return (
  <div>
    <h1>标题</h1>
    <p>内容</p>
  </div>
);

// ✅ 正确:使用Fragment
return (
  <>
    <h1>标题</h1>
    <p>内容</p>
  </>
);

// ✅ 正确:使用React.Fragment
return (
  <React.Fragment>
    <h1>标题</h1>
    <p>内容</p>
  </React.Fragment>
);

三、嵌入表达式 #

3.1 使用花括号 #

在 JSX 中使用 {} 嵌入 JavaScript 表达式:

javascript
const name = 'React';
const age = 10;

const element = (
  <div>
    <h1>Hello, {name}!</h1>
    <p>Age: {age}</p>
    <p>Next Year: {age + 1}</p>
  </div>
);

3.2 可嵌入的内容 #

javascript
// 变量
const name = 'React';
<div>{name}</div>

// 表达式
<div>{1 + 1}</div>
<div>{'Hello'.toUpperCase()}</div>

// 函数调用
function formatName(user) {
  return user.firstName + ' ' + user.lastName;
}
<div>{formatName({ firstName: 'React', lastName: 'JS' })}</div>

// 三元表达式
const isLoggedIn = true;
<div>{isLoggedIn ? '欢迎回来' : '请登录'}</div>

// 逻辑与运算符
const messages = ['msg1', 'msg2'];
<div>{messages.length > 0 && '有新消息'}</div>

3.3 不能嵌入的内容 #

javascript
// ❌ 不能嵌入语句
<div>{if (true) { return 'yes' }}</div>
<div>{for (let i = 0; i < 5; i++) { }}</div>
<div>{var x = 1}</div>

// ✅ 使用表达式替代
<div>{true ? 'yes' : 'no'}</div>
<div>{[1, 2, 3, 4, 5].map(i => i)}</div>

四、属性设置 #

4.1 字符串属性 #

javascript
// 使用引号
const img = <img src="logo.png" alt="Logo" />;
const div = <div className="container">内容</div>;
const input = <input type="text" placeholder="请输入" />;

4.2 动态属性 #

javascript
const imageUrl = 'logo.png';
const altText = 'Logo';

const img = <img src={imageUrl} alt={altText} />;

4.3 特殊属性名 #

HTML 属性在 JSX 中需要转换:

HTML JSX
class className
for htmlFor
tabindex tabIndex
readonly readOnly
maxlength maxLength
onclick onClick
onchange onChange
javascript
// ❌ 错误
<div class="container">
  <label for="name">Name</label>
</div>

// ✅ 正确
<div className="container">
  <label htmlFor="name">Name</label>
</div>

4.4 布尔属性 #

javascript
// 省略值表示true
<input disabled />
<input required />

// 显式设置
<input disabled={true} />
<input disabled={false} />

4.5 data-* 和 aria-* 属性 #

javascript
<div data-id="123" data-name="test">内容</div>
<button aria-label="关闭">X</button>

五、样式设置 #

5.1 内联样式 #

javascript
const style = {
  color: 'red',
  fontSize: '16px',
  backgroundColor: '#f0f0f0',
  padding: '10px 20px'
};

const div = <div style={style}>内容</div>;

// 直接写对象
const div2 = (
  <div style={{
    color: 'blue',
    fontSize: '14px'
  }}>
    内容
  </div>
);

注意

  • 使用 camelCase 命名
  • 值可以是字符串或数字
  • 数字会自动添加 px

5.2 CSS类名 #

javascript
// 单个类名
<div className="container">内容</div>

// 多个类名
<div className="container active">内容</div>

// 动态类名
const isActive = true;
<div className={`container ${isActive ? 'active' : ''}`}>
  内容
</div>

// 使用模板字符串
const size = 'large';
<div className={`button button-${size}`}>
  按钮
</div>

5.3 使用classnames库 #

bash
npm install classnames
javascript
import classNames from 'classnames';

function Button({ primary, size, disabled }) {
  const btnClass = classNames('btn', {
    'btn-primary': primary,
    'btn-large': size === 'large',
    'btn-small': size === 'small',
    'btn-disabled': disabled
  });

  return <button className={btnClass}>按钮</button>;
}

六、条件渲染 #

6.1 if语句 #

javascript
function Greeting({ isLoggedIn }) {
  if (isLoggedIn) {
    return <h1>欢迎回来!</h1>;
  }
  return <h1>请登录</h1>;
}

6.2 三元表达式 #

javascript
function Greeting({ isLoggedIn }) {
  return (
    <div>
      {isLoggedIn ? <h1>欢迎回来!</h1> : <h1>请登录</h1>}
    </div>
  );
}

6.3 逻辑与运算符 #

javascript
function Mailbox({ unreadMessages }) {
  return (
    <div>
      <h1>Hello!</h1>
      {unreadMessages.length > 0 && (
        <h2>你有 {unreadMessages.length} 条未读消息</h2>
      )}
    </div>
  );
}

6.4 立即执行函数 #

javascript
function Component({ type }) {
  return (
    <div>
      {(() => {
        switch (type) {
          case 'a': return <A />;
          case 'b': return <B />;
          default: return <C />;
        }
      })()}
    </div>
  );
}

七、列表渲染 #

7.1 map方法 #

javascript
const fruits = ['Apple', 'Banana', 'Orange'];

const list = (
  <ul>
    {fruits.map((fruit, index) => (
      <li key={index}>{fruit}</li>
    ))}
  </ul>
);

7.2 对象列表 #

javascript
const users = [
  { id: 1, name: 'Alice', age: 25 },
  { id: 2, name: 'Bob', age: 30 },
  { id: 3, name: 'Charlie', age: 35 }
];

const userList = (
  <ul>
    {users.map(user => (
      <li key={user.id}>
        {user.name} - {user.age}岁
      </li>
    ))}
  </ul>
);

7.3 key的重要性 #

javascript
// ✅ 使用唯一ID作为key
{items.map(item => <li key={item.id}>{item.name}</li>)}

// ⚠️ 避免使用index作为key(列表会变化时)
{items.map((item, index) => <li key={index}>{item.name}</li>)}

// ❌ 不要使用不稳定的key(如随机数)
{items.map(item => <li key={Math.random()}>{item.name}</li>)}

key的作用

  • 帮助 React 识别列表项的变化
  • 提高列表更新性能
  • 保持组件状态正确

八、事件处理 #

8.1 绑定事件 #

javascript
function Button() {
  const handleClick = () => {
    console.log('按钮被点击');
  };

  return <button onClick={handleClick}>点击我</button>;
}

8.2 传递参数 #

javascript
function List() {
  const handleClick = (id, event) => {
    console.log('ID:', id);
    console.log('Event:', event);
  };

  return (
    <ul>
      <li onClick={(e) => handleClick(1, e)}>Item 1</li>
      <li onClick={(e) => handleClick(2, e)}>Item 2</li>
    </ul>
  );
}

8.3 阻止默认行为 #

javascript
function Form() {
  const handleSubmit = (e) => {
    e.preventDefault();
    console.log('表单提交');
  };

  return (
    <form onSubmit={handleSubmit}>
      <button type="submit">提交</button>
    </form>
  );
}

九、组件使用 #

9.1 使用组件 #

javascript
function Header() {
  return <h1>Header</h1>;
}

function Content() {
  return <p>Content</p>;
}

function App() {
  return (
    <div>
      <Header />
      <Content />
    </div>
  );
}

9.2 组件属性 #

javascript
function Welcome({ name, age }) {
  return (
    <div>
      <h1>Hello, {name}!</h1>
      <p>Age: {age}</p>
    </div>
  );
}

function App() {
  return (
    <div>
      <Welcome name="Alice" age={25} />
      <Welcome name="Bob" age={30} />
    </div>
  );
}

9.3 children属性 #

javascript
function Card({ title, children }) {
  return (
    <div className="card">
      <h2>{title}</h2>
      <div className="card-body">
        {children}
      </div>
    </div>
  );
}

function App() {
  return (
    <Card title="标题">
      <p>这是卡片内容</p>
      <button>按钮</button>
    </Card>
  );
}

十、JSX最佳实践 #

10.1 代码组织 #

javascript
// ✅ 好的做法:逻辑与渲染分离
function UserList({ users }) {
  const activeUsers = users.filter(user => user.isActive);
  const sortedUsers = activeUsers.sort((a, b) => a.name.localeCompare(b.name));

  return (
    <ul>
      {sortedUsers.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

10.2 条件渲染优化 #

javascript
// ✅ 复杂条件抽取为函数
function getStatusText(status) {
  switch (status) {
    case 'loading': return '加载中...';
    case 'success': return '成功';
    case 'error': return '出错了';
    default: return '未知状态';
  }
}

function Component({ status }) {
  return <div>{getStatusText(status)}</div>;
}

10.3 避免嵌套过深 #

javascript
// ❌ 嵌套过深
return (
  <div>
    <div>
      <div>
        <div>
          <span>内容</span>
        </div>
      </div>
    </div>
  </div>
);

// ✅ 使用Fragment或拆分组件
return (
  <>
    <Header />
    <Main />
    <Footer />
  </>
);

十一、总结 #

JSX规则 说明
单根元素 返回一个父元素
闭合标签 所有标签必须闭合
camelCase 属性使用驼峰命名
className 使用 className 代替 class
花括号 使用 {} 嵌入表达式
key属性 列表渲染需要唯一 key

核心要点:

  • JSX 是语法糖,编译为 JavaScript
  • 使用 {} 嵌入 JavaScript 表达式
  • 属性使用驼峰命名
  • 条件渲染使用三元表达式或逻辑与
  • 列表渲染使用 map 方法
最后更新:2026-03-26