JSX 语法
下面,我们来系统的梳理关于 JSX 语法 的基本知识点:
一、JSX 核心概念
1.1 什么是 JSX?
JSX (JavaScript XML) 是 React 的核心语法扩展,它允许你在 JavaScript 代码中编写类似 HTML 的结构。JSX 不是字符串也不是 HTML,而是JavaScript 的语法糖,最终会被编译为 React.createElement()
调用。
// JSX 写法
const element = <h1 className="title">Hello, React!</h1>;// 编译后的 JavaScript
const element = React.createElement('h1',{ className: 'title' },'Hello, React!'
);
1.2 为什么使用 JSX?
- 声明式UI:直观描述 UI 结构
- 代码可读性:类似 HTML 的语法更易理解
- 表达能力:结合 JavaScript 的强大功能
- 类型安全:与 TypeScript 完美集成
- 开发效率:减少模板代码量
二、JSX 基础语法
2.1 基本规则
- 必须有一个根元素:使用
<></>
片段避免多余 DOM
// 错误:多个根元素
const invalid = (<h1>Title</h1><p>Content</p>
);// 正确:单根元素或片段
const valid = (<><h1>Title</h1><p>Content</p></>
);
- 标签必须闭合
// 自闭合标签
<img src="logo.png" alt="Logo" />// 常规标签
<div>Content</div>
2.2 嵌入表达式
使用 {}
嵌入任何 JavaScript 表达式:
const user = {name: 'Alice',avatarUrl: 'avatar.jpg'
};const element = (<div><h1>Hello, {user.name}!</h1><img src={user.avatarUrl} alt="Avatar" /><p>2 + 2 = {2 + 2}</p><p>当前时间: {new Date().toLocaleTimeString()}</p></div>
);
2.3 属性命名规范
JSX 使用 camelCase 命名属性:
HTML 属性 | JSX 属性 | 说明 |
---|---|---|
class | className | CSS 类名 |
for | htmlFor | 标签的 for 属性 |
tabindex | tabIndex | 标签顺序 |
onclick | onClick | 点击事件处理 |
style | style | 接受对象而非字符串 |
<div className="container"tabIndex={1}style={{ backgroundColor: 'lightblue',padding: '20px'}}
>Content
</div>
三、JSX 高级特性
3.1 条件渲染
多种条件渲染模式:
// 1. 三元表达式
const message = (<div>{isLoggedIn ? (<WelcomeMessage user={user} />) : (<LoginButton />)}</div>
);// 2. 逻辑与(&&)短路
const notification = (<div>{hasUnreadMessages && <NotificationBadge count={unreadCount} />}</div>
);// 3. 立即执行函数
const complexCondition = (<div>{(() => {if (status === 'loading') return <Spinner />;if (status === 'error') return <ErrorDisplay />;return <Content data={data} />;})()}</div>
);
3.2 列表渲染
使用 map()
渲染列表,必须提供 key 属性:
const products = [{ id: 1, name: 'Laptop', price: 999 },{ id: 2, name: 'Phone', price: 699 },{ id: 3, name: 'Tablet', price: 499 }
];const productList = (<ul>{products.map(product => (<li key={product.id}><h3>{product.name}</h3><p>Price: ${product.price}</p></li>))}</ul>
);
key 的重要性:帮助 React 识别元素变化,提高 diff 算法效率
3.3 事件处理
使用 camelCase 命名事件,传递函数而非字符串:
function handleClick(e) {e.preventDefault();console.log('Button clicked!');
}const button = (<button onClick={handleClick}>Click Me</button>
);
3.4 组件组合
JSX 支持组件嵌套和插槽模式:
// 父组件
function Card({ title, children }) {return (<div className="card"><h2>{title}</h2><div className="card-content">{children} {/* 子内容插槽 */}</div></div>);
}// 使用
const app = (<Card title="User Profile"><img src="avatar.jpg" alt="Avatar" /><p>Name: John Doe</p><p>Email: john@example.com</p></Card>
);
四、JSX 底层原理
4.1 JSX 编译过程
JSX 通过 Babel 编译为 React.createElement 调用:
// 源代码
const element = <div className="container">Hello</div>;// 编译后
const element = React.createElement('div',{ className: 'container' },'Hello'
);
4.2 React 元素对象
createElement
返回 React 元素对象:
{$$typeof: Symbol(react.element),type: 'div',key: null,ref: null,props: {className: 'container',children: 'Hello'},_owner: null,_store: {}
}
4.3 虚拟 DOM 工作原理
五、JSX 最佳实践与陷阱
5.1 最佳实践
- 保持 JSX 简洁:复杂逻辑提取到函数/组件
- 使用片段:避免不必要的
<div>
嵌套 - 条件渲染优先:使用 && 和三元表达式
- key 属性:列表项必须使用稳定唯一标识
- 组件拆分:单个组件不超过 200 行 JSX
5.2 常见陷阱
// 陷阱1:直接渲染对象
const user = { name: 'Alice' };
<div>{user}</div> // 错误!应使用 {user.name}// 陷阱2:style 属性使用字符串
<div style="color: red"> // 错误!
<div style={{ color: 'red' }}> // 正确// 陷阱3:未转义用户输入
<div>{userInput}</div> // 危险!可能XSS攻击
<div>{sanitize(userInput)}</div> // 安全做法// 陷阱4:忘记绑定this
<button onClick={this.handleClick}>Click</button> // 类组件中需绑定
六、JSX 与 TypeScript
6.1 类型注解
interface UserCardProps {name: string;age: number;isAdmin?: boolean; // 可选属性
}function UserCard({ name, age, isAdmin = false }: UserCardProps) {return (<div className="user-card"><h2>{name} {isAdmin && <span>(Admin)</span>}</h2><p>Age: {age}</p></div>);
}
6.2 泛型组件
interface ListProps<T> {items: T[];renderItem: (item: T) => React.ReactNode;
}function List<T>({ items, renderItem }: ListProps<T>) {return (<ul>{items.map((item, index) => (<li key={index}>{renderItem(item)}</li>))}</ul>);
}// 使用
<List items={['React', 'Vue', 'Angular']} renderItem={(item) => <strong>{item}</strong>}
/>
七、实战练习
7.1 转换练习
将以下 HTML 转换为正确 JSX:
<div class="profile"><img src="user.jpg" alt="User photo"><h1 id="username">John Doe</h1><ul class="features"><li>React Developer</li><li>UI Designer</li></ul><button onclick="handleClick()">Follow</button>
</div>
查看答案
<div className="profile"><img src="user.jpg" alt="User photo" /><h1 id="username">John Doe</h1><ul className="features"><li>React Developer</li><li>UI Designer</li></ul><button onClick={handleClick}>Follow</button>
</div>
7.2 组件练习
创建可复用的 Accordion
组件:
function Accordion({ title, children }) {const [isOpen, setIsOpen] = useState(false);return (<div className="accordion"><div className="header" onClick={() => setIsOpen(!isOpen)}><h3>{title}</h3><span>{isOpen ? '▲' : '▼'}</span></div>{isOpen && <div className="content">{children}</div>}</div>);
}// 使用
<Accordion title="React 知识"><p>JSX 是 React 的核心语法</p><p>组件是构建 UI 的基础单元</p>
</Accordion>
八、总结
- JSX 是 React 的声明式 UI 语法糖
- 使用
{}
嵌入表达式,camelCase
命名属性 - 掌握条件渲染、列表渲染和组件组合模式
- 理解 JSX 编译为
React.createElement
的底层原理 - 遵循最佳实践避免常见陷阱
- 结合 TypeScript 增强类型安全