ReactJSX语法详解

JSX是React的核心特性之一,它允许您在JavaScript中编写类似HTML的代码,使组件开发更加直观和高效。

什么是JSX?

JSX(JavaScript XML)是JavaScript的语法扩展,它允许您在JavaScript代码中编写HTML-like标签。JSX最终会被编译为普通的JavaScript函数调用(React.createElement())。

JSX示例:

// JSX语法
const element = <h1 className="greeting">Hello, JSX!</h1>

// 编译后的JavaScript
const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, JSX!'
);
                        

JSX基本语法规则

1. 必须有一个根元素

正确写法:

const element = (
  <div>
    <h1>标题</h1>
    <p>段落内容</p>
  </div>
);
                        
错误写法:

// 错误:多个根元素
const element = (
  <h1>标题</h1>
  <p>段落内容</p>
);
                        

2. 标签必须闭合

自闭合标签:

<img src="..." alt="..." />
<input type="text" />
<br />
                                
成对闭合标签:

<div>内容</div>
<span>文本</span>
<p>段落</p>
                                

3. 使用className代替class

因为class是JavaScript的保留字,所以在JSX中使用className来设置CSS类。

// JSX中的class属性
const element = <div className="container active">内容</div>

// 编译后的HTML
// <div class="container active">内容</div>
                    

在JSX中嵌入表达式

JSX最强大的功能之一是在大括号{}中嵌入任何JavaScript表达式。

变量嵌入

const name = 'React开发者';
const element = <h1>你好,{name}!</h1>
                                    
表达式计算

const a = 5;
const b = 10;
const element = <p>计算结果: {a + b}</p>
                                    
函数调用

function formatName(user) {
  return user.firstName + ' ' + user.lastName;
}

const user = {firstName: '张', lastName: '三'};
const element = <h1>你好,{formatName(user)}!</h1>
                                    
对象属性

const user = {
  name: '李四',
  age: 25,
  job: '前端工程师'
};

const element = (
  <div>
    <p>姓名: {user.name}</p>
    <p>年龄: {user.age}</p>
    <p>职业: {user.job}</p>
  </div>
);
                                    

JSX中的条件渲染

在JSX中,您可以使用多种方式实现条件渲染。

1. 三元运算符


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

2. 逻辑与操作符 (&&)


function Notification(props) {
  return (
    <div>
      <h1>消息中心</h1>
      {props.hasNewMessages && <span className="badge">新消息</span>}
      {props.messageCount > 0 && (
        <p>您有 {props.messageCount} 条未读消息</p>
      )}
    </div>
  );
}
                    

3. 立即执行函数


function UserStatus(props) {
  return (
    <div>
      {(() => {
        if (props.status === 'online') {
          return <span className="online">在线</span>
        } else if (props.status === 'offline') {
          return <span className="offline">离线</span>
        } else {
          return <span className="away">离开</span>
        }
      })()}
    </div>
  );
}
                    

JSX中的列表渲染

使用JavaScript的map()方法渲染列表,注意每个元素都需要一个唯一的key属性。


function TodoList() {
  const todos = [
    {id: 1, text: '学习React', completed: true},
    {id: 2, text: '学习JSX', completed: false},
    {id: 3, text: '构建项目', completed: false}
  ];

  return (
    <ul className="todo-list">
      {todos.map(todo => (
        <li key={todo.id} className={todo.completed ? 'completed' : ''}>
          {todo.text}
          {!todo.completed && <button>标记完成</button>}
        </li>
      ))}
    </ul>
  );
}
                    
重要提示: key属性帮助React识别哪些元素改变了,应该给数组中的每个元素赋予一个稳定的标识。尽量避免使用数组索引作为key,除非列表是静态的。

JSX中的样式设置

1. 内联样式

使用JavaScript对象设置内联样式,属性名需要使用驼峰命名法。


function StyledComponent() {
  const style = {
    backgroundColor: '#61dafb',
    color: 'white',
    padding: '20px',
    borderRadius: '8px',
    fontSize: '1.2rem',
    fontWeight: 'bold'
  };

  return (
    <div style={style}>
      这是一个带样式的组件
    </div>
  );
}
                    

2. 动态样式


function Alert(props) {
  const alertStyle = {
    padding: '15px',
    borderRadius: '5px',
    margin: '10px 0',
    backgroundColor: props.type === 'error' ? '#f8d7da' :
                     props.type === 'warning' ? '#fff3cd' : '#d1ecf1',
    color: props.type === 'error' ? '#721c24' :
           props.type === 'warning' ? '#856404' : '#0c5460',
    border: `1px solid ${props.type === 'error' ? '#f5c6cb' :
                        props.type === 'warning' ? '#ffeaa7' : '#bee5eb'}`
  };

  return <div style={alertStyle}>{props.message}</div>
}
                    

JSX中的事件处理

JSX中的事件处理使用驼峰命名法,传递函数作为事件处理器。


function Counter() {
  const [count, setCount] = React.useState(0);

  const handleClick = () => {
    setCount(count + 1);
  };

  const handleReset = (event) => {
    event.preventDefault(); // 阻止默认行为
    setCount(0);
  };

  return (
    <div>
      <p>计数: {count}</p>
      <button onClick={handleClick}>
        点击增加
      </button>
      <button onClick={handleReset}>
        重置
      </button>
      <button onClick={() => setCount(count - 1)}>
        减少
      </button>
    </div>
  );
}
                    

JSX与HTML的差异对比

特性 HTML JSX
类名 class="container" className="container"
内联样式 style="color: red;" style={color: 'red'}
事件处理 onclick="handleClick()" onClick={handleClick}
标签闭合 <br> <br />
for属性 for="name" htmlFor="name"
tabindex属性 tabindex="1" tabIndex="1"

JSX最佳实践

推荐做法
  • 保持JSX简洁,复杂逻辑提取为函数
  • 使用括号包裹多行JSX
  • 为列表元素添加稳定的key
  • 使用语义化的HTML标签
  • 提取重复的JSX为组件
避免做法
  • 避免在JSX中写复杂逻辑
  • 不要使用数组索引作为key
  • 不要忘记闭合标签
  • 避免内联样式过多
  • 不要混用class和className

完整示例:用户卡片组件


function UserCard(props) {
  const { user } = props;

  // 计算用户等级
  const getUserLevel = (score) => {
    if (score >= 1000) return '金牌';
    if (score >= 500) return '银牌';
    if (score >= 100) return '铜牌';
    return '新手';
  };

  return (
    <div className="user-card" style={
      border: '1px solid #ddd',
      borderRadius: '8px',
      padding: '20px',
      margin: '10px',
      backgroundColor: '#f9f9f9'
    }>
      <div className="user-header">
        <img
          src={user.avatar}
          alt={user.name}
          style={width: '80px', height: '80px', borderRadius: '50%'}
        />
        <div className="user-info">
          <h3>{user.name}</h3>
          <span className={`badge badge-${getUserLevel(user.score).toLowerCase()}`}>
            {getUserLevel(user.score)}
          </span>
        </div>
      </div>

      <div className="user-details">
        <p><strong>邮箱:</strong> {user.email}</p>
        <p><strong>积分:</strong> {user.score}</p>
        <p><strong>加入时间:</strong> {new Date(user.joinDate).toLocaleDateString()}</p>
      </div>

      {user.isOnline && (
        <div className="user-status" style={color: 'green', fontWeight: 'bold'}>
          ⚫ 在线
        </div>
      )}
    </div>
  );
}
                    

学习要点总结

  • JSX是JavaScript的语法扩展,不是模板语言
  • 使用大括号{}嵌入JavaScript表达式
  • 使用className而不是class
  • 每个元素必须有一个唯一的key
  • 事件处理使用驼峰命名法
  • 样式属性使用JavaScript对象