JSX 的产物是 JavaScript 对象
既然 JSX 会被转换为 React.createElement(),那么这个函数执行后会返回什么呢?
答案是:一个普通的 JavaScript 对象。
这个对象通常被称为“React 元素(React Element)”,它像一张蓝图,描述了我们希望在屏幕上看到的 UI 结构。以上面的 element 为例,React.createElement() 执行后得到的对象,大致会是这样:
{
type: 'h1',
props: {
className: 'greeting',
children: 'Hello, world!'
},
// ... 其他内部属性
}这个对象并不直接操作 DOM。它只是一个轻量的数据结构,用来告诉 React:“嘿,我想要渲染一个 h1 标签,它的 class 是 greeting,里面的内容是 Hello, world!。” React 会收集这些对象,构建出我们常说的虚拟 DOM(Virtual DOM),再高效地计算出如何更新真实的浏览器 DOM。
所以,当我们编写 JSX 时,我们实际上是在用一种便捷的方式创建和组合 JavaScript 对象。
JSX 内部可以无缝嵌入 JavaScript 的全部能力
这或许是 JSX 作为“JavaScript 扩展”最有力的证明。在传统的模板引擎(如 Handlebars 或 EJS)中,我们通常只能使用其提供的特定语法来进行逻辑判断(如 {{#if}})或循环(如 {{#each}})。这些语法是受限的,它们自成体系,与 JavaScript 本身是割裂的。
而 JSX 完全不同。通过 {} 括号,我们可以在 JSX 中嵌入任何有效的 JavaScript 表达式。这意味着我们可以直接利用 JavaScript 语言的全部能力来构建动态 UI。
变量与表达式
- 我们可以直接引用变量,或进行简单的运算。
const user = { firstName: 'Harper', lastName: 'Perez' };
const element = <h1>Hello, {user.firstName} {user.lastName}!</h1>;函数调用
- 在渲染过程中执行函数,并将返回值作为内容。
function formatName(user) {
return user.firstName + ' ' + user.lastName;
}
const element = <h1>Hello, {formatName(user)}!</h1>;条件渲染
- 利用三元运算符或逻辑与(
&&)操作符,可以轻松实现条件渲染。
// 使用三元运算符
<div>
{isLoggedIn ? <LogoutButton /> : <LoginButton />}
</div>
// 使用 && 操作符
<div>
<h1>Hello!</h1>
{unreadMessages.length > 0 &&
<h2>
You have {unreadMessages.length} unread messages.
</h2>
}
</div>列表渲染
Array.prototype.map()是JavaScript的原生方法,在JSX中用于列表渲染是极其自然和常见的模式。map方法返回一个由JSX元素构成的新数组,React会将其渲染为列表。
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li key={number.toString()}>{number}</li>
);
// 最终渲染 <ul>{listItems}</ul>结论
综上所述,JSX 的精妙之处在于它并非一种与 JavaScript 分离的模板技术。
它是一种语法扩展,为
React.createElement()提供了更具可读性和表现力的声明式写法。它的最终产物是纯粹的
JavaScript对象,这构成了React虚拟DOM的基础。它允许我们无缝地利用
JavaScript的全部功能,包括变量、函数、条件逻辑和循环,从而构建出复杂而动态的用户界面。
当我们说 JSX 是 JavaScript 的扩展时,我们强调的是它与 JavaScript 语言的深度融合。这种融合打破了传统“逻辑层”与“视图层”之间的壁垒,为我们带来了一种更内聚、更强大的组件化开发体验。
