JSX(JavaScript XML)是JavaScript的语法扩展,它允许您在JavaScript代码中编写HTML-like标签。JSX最终会被编译为普通的JavaScript函数调用(React.createElement())。
// JSX语法
const element = <h1 className="greeting">Hello, JSX!</h1>
// 编译后的JavaScript
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, JSX!'
);
const element = (
<div>
<h1>标题</h1>
<p>段落内容</p>
</div>
);
// 错误:多个根元素
const element = (
<h1>标题</h1>
<p>段落内容</p>
);
<img src="..." alt="..." />
<input type="text" />
<br />
<div>内容</div>
<span>文本</span>
<p>段落</p>
class是JavaScript的保留字,所以在JSX中使用className来设置CSS类。
// JSX中的class属性
const element = <div className="container active">内容</div>
// 编译后的HTML
// <div class="container active">内容</div>
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中,您可以使用多种方式实现条件渲染。
function Greeting(props) {
return (
<div>
{props.isLoggedIn ? (
<h1>欢迎回来!</h1>
) : (
<h1>请先登录</h1>
)}
</div>
);
}
function Notification(props) {
return (
<div>
<h1>消息中心</h1>
{props.hasNewMessages && <span className="badge">新消息</span>}
{props.messageCount > 0 && (
<p>您有 {props.messageCount} 条未读消息</p>
)}
</div>
);
}
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>
);
}
使用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,除非列表是静态的。
使用JavaScript对象设置内联样式,属性名需要使用驼峰命名法。
function StyledComponent() {
const style = {
backgroundColor: '#61dafb',
color: 'white',
padding: '20px',
borderRadius: '8px',
fontSize: '1.2rem',
fontWeight: 'bold'
};
return (
<div style={style}>
这是一个带样式的组件
</div>
);
}
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中的事件处理使用驼峰命名法,传递函数作为事件处理器。
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>
);
}
| 特性 | 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" |
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>
);
}
{}嵌入JavaScript表达式className而不是classkey