二、React JSX
1. 什么是JSX
JSX是React中的一项核心技术,本质上是JavaScript的语法扩展(JavaScript XML)。根据最新的React文档,JSX被定义为"在JavaScript中嵌入类似HTML的标签语法",它允许我们直观地描述UI应该呈现的样子。
从本质上看,JSX是React.createElement()函数的语法糖,它使UI结构的描述更加直观和可读。React团队创造JSX的初衷是基于组件应该包含其渲染逻辑和标记的理念,而不是将它们人为分离到不同文件中。
在最新的React版本(React 17及以上)中,JSX已经得到了进一步优化。新的JSX转换不再要求在使用JSX的文件顶部导入React,这使代码更加简洁。JSX现在已成为React开发的标志性特征,它成功地将声明式UI编程与JavaScript的全部能力无缝结合。
2. JSX的语法规则
标签闭合规则
所有标签必须显式闭合:自闭合标签(如 <img />
)或成对闭合标签(如 <div></div>
)。
单一根元素
组件必须返回单个根元素。多个元素需包裹在父容器中,推荐使用空标签 <>...</>(Fragment)避免额外 DOM 节点。
JavaScript 表达式嵌入
用 { } 包裹任意 JavaScript 表达式(变量、函数调用等),例如: {user.name} 或 {calculateTotal()}。
驼峰式属性命名
HTML 属性改为 camelCase:
- className 代替 class
- onClick 代替 onclick
- htmlFor 代替 for
条件渲染
推荐方式:
- 三元表达式:{isLoggedIn ? : }
- && 短路运算:{hasItems && }
- 提取逻辑到独立函数
列表渲染与 key
用 map() 渲染数组元素,必须为每个项添加唯一 key(通常用 ID):
{items.map(item => <li key={item.id}>{item.name}</li>)}
事件处理
事件名用 camelCase(如 onClick),直接传递函数引用: (非字符串 "handleClick()")
React 18的文档更加强调了JSX的声明式特性,鼓励开发者"描述UI应该是什么样子",而不是手动操作DOM元素。
3. JSX的使用方法
在实际项目中,我经常以下面的方式使用JSX:
-
导入必要的依赖:React项目中需要导入React核心库,即使不直接使用React对象,也需要导入(React 17之前):
import React from 'react';
-
创建组件:使用JSX语法定义组件结构:
function Welcome() { const name = "React学习者"; return <h1>你好, {name}</h1>; }
-
组合组件:将多个组件组合成更复杂的UI结构:
function App() { return ( <div> <Welcome /> <div className="container"> <p>这是一个JSX示例</p> </div> </div> ); }
-
处理事件:在JSX中绑定事件处理函数:
function Button() { const handleClick = () => alert('按钮被点击'); return <button onClick={handleClick}>点击我</button>; }
-
列表渲染:使用map方法渲染列表项:
function List() { const items = ['React', 'Vue', 'Angular']; return ( <ul> {items.map(item => <li key={item}>{item}</li>)} </ul> ); }
通过这些使用方式,JSX让我们能够直观地表达UI结构,同时保持JavaScript的全部能力,这是JSX的魅力所在。
4. 渲染虚拟DOM(元素)
JSX最终会创建"虚拟DOM"对象,而不是真实的DOM元素。这是React性能优化的关键。虚拟DOM渲染过程如下:
-
创建虚拟DOM:JSX代码被转换为React.createElement()调用,创建虚拟DOM对象。
-
渲染到容器:通过ReactDOM.render()方法将虚拟DOM渲染到真实DOM容器中:
ReactDOM.render(<App />, document.getElementById('root'));
(在React 18中,这已被createRoot API替代)
- 更新过程:当组件状态或属性变化时,React会重新生成新的虚拟DOM树,通过Diff算法比较新旧虚拟DOM,计算最小变更集,然后只更新必要的真实DOM节点。
这种机制有效减少了直接操作DOM的开销,特别是在频繁更新的应用中,性能提升明显。我认为虚拟DOM是React框架的一大亮点,它使得声明式UI成为可能,开发者只需关注"UI应该是什么样子",而不必关心"如何更新DOM"的具体细节。
5. JSX与JavaScript的关系
我认为JSX与JavaScript的关系可以从以下几个层面来理解:
JSX的出现体现了前端开发思想的演进,它没有抛弃JavaScript,而是在其基础上构建了更适合UI开发的抽象层,这是一种优雅的设计。
6. JSX编译过程
JSX的编译过程是React技术栈中不可或缺的环节,经过学习与探讨,我总结了以下关键步骤:
-
解析阶段:Babel等编译工具首先将JSX代码解析成抽象语法树(AST)。
-
转换阶段:编译器将JSX语法转换为React.createElement()函数调用。例如:
<div className="greeting">Hello, {name}</div>
会被转换为:
React.createElement(
'div',
{ className: 'greeting' },
'Hello, ',
name
);
-
优化阶段:现代编译器(如Babel 7+配合preset-react)会进行优化,如自动导入JSX运行时、静态分析等。
-
运行时处理:在浏览器运行时,React.createElement()创建虚拟DOM对象(React元素),描述UI的结构和属性。
-
渲染阶段:React使用这些虚拟DOM对象,通过调和过程(Reconciliation)决定如何高效地更新实际DOM。
这个编译过程体现了React的设计哲学:在开发时提供声明式API(JSX)以提升开发效率,而在运行时转换为高效的命令式代码。值得一提的是,React 17引入了新的JSX转换机制,不再要求显式导入React,这是编译优化的一个典型例子。随着工具链的发展,JSX编译过程也在不断优化,但核心理念保持不变——让开发者以最自然的方式表达UI,同时保持高效的运行时性能。
[面试常问 ]
JSX 如何防止 XSS 攻击?
React 通常通过以下方式防止 XSS 攻击:
1.自动转义:
- 当在 JSX 中插入内容时,React 会自动对内容进行转义
- 这意味着即使内容包含恶意代码,也会被渲染为文本而不是执行
2.dangerouslySetInnerHTML 的安全警告:
- React 通过命名明确警告开发者使用该属性的风险
- 强制开发者显式地传递 HTML 内容,而不是隐式地插入
3.组件封装:
- React 鼓励使用组件封装 UI 逻辑
- 这使得更容易控制数据流向和确保输入的安全性
这些措施共同确保了 React 应用在默认情况下对 XSS 攻击具有较高的抵抗力。