最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
第 2 篇:JSX 与模板语法
时间:2026-07-24 10:42:56 编辑:袖梨 来源:一聚教程网
Vue 把 UI 写在 <template> 里,用指令(v-if、v-for、:class)操作它。React 则完全相反:它把 UI 写进 JavaScript,这种语法叫 JSX。一开始会觉得别扭,但理解之后你会发现它异常灵活——因为它就是 JS,你会的所有 JS 技巧都能用。

一、第一眼对比
Vue3 SFC:
复制代码<template>
<div class="card">
<h2>{{ title }}</h2>
<p v-if="desc">{{ desc }}</p>
</div>
</template><script setup>
const title = 'Hello'
const desc = 'World'
</script>
React:
复制代码function Card() {
const title = 'Hello'
const desc = 'World' return (
<div className="card">
<h2>{title}</h2>
{desc && <p>{desc}</p>}
</div>
)
}
注意三点:
- UI 直接
return出来,和逻辑写在同一个函数里; - 插值用单大括号
{title},不是 Vue 的双大括号{{ }}; class要写成className(因为 JSX 本质是 JS,class是保留字)。
二、插值:{ } 里能放任何 JS 表达式
Vue 的 {{ }} 里也能写表达式,但 React 的 { } 更彻底——任何合法的 JS 表达式都行:
复制代码function Demo({ user, items }) {
return (
<div>
<p>{user.name.toUpperCase()}</p>
<p>{user.age >= 18 ? '成年' : '未成年'}</p>
<p>{items.length} 个项目</p>
<p>{new Date().getFullYear()}</p>
</div>
)
}
记住:{ } 里放的是表达式(有返回值的),不能放 if、for 这类语句。需要条件/循环时,用三元、&&、.map()(下一节讲)。
三、属性绑定:告别 : 前缀
| 场景 | Vue3 | React |
|---|---|---|
| 静态属性 | type="text" | type="text" |
| 动态属性 | :href="url" | href={url} |
| 布尔属性 | :disabled="isDisabled" | disabled={isDisabled} |
Vue 用 : 区分静态和动态,React 用是否加大括号来区分:引号是字符串,大括号是 JS 值。
复制代码<img src={imageUrl} alt="头像" width={120} />
<button disabled={loading}>提交</button>
几个必须改名的属性
因为 JSX 是 JS,一些 HTML 属性名会和 JS 关键字冲突,需要改成驼峰:
| HTML / Vue | React |
|---|---|
class | className |
for(label) | htmlFor |
tabindex | tabIndex |
onclick | onClick(驼峰事件) |
四、class 与 style 绑定
这是 Vue 开发者最不习惯的地方,因为 Vue 提供了强大的对象/数组语法糖,而 React 需要你用纯 JS 拼。
class
复制代码<!-- Vue3 -->
<div :class="{ active: isActive, 'text-danger': hasError }"></div>
<div :class="['base', isActive ? 'on' : 'off']"></div>
复制代码// React:用模板字符串或三元自己拼
<div className={`base ${isActive ? 'on' : 'off'}`}></div>// 条件较多时,社区常用 clsx / classnames 库(对标 Vue 的对象语法)
import clsx from 'clsx'
<div className={clsx('base', { active: isActive, 'text-danger': hasError })}></div>
style
Vue 里 style 可以是字符串或对象;React 只接受对象,且属性用驼峰、值大多要带单位字符串:
复制代码<!-- Vue3 -->
<div :style="{ color: 'red', fontSize: '14px' }"></div>
复制代码// React
<div style={{ color: 'red', fontSize: '14px' }}></div>
注意那两层大括号:外层是 JSX 插值,内层是 JS 对象字面量。
五、根节点:Fragment 对应 Vue 的多根
Vue3 支持组件多根节点,React 也支持,但需要用 Fragment 包裹(避免多余的 DOM 层级):
复制代码import { Fragment } from 'react'function List() {
return (
<>
<li>A</li>
<li>B</li>
</>
)
}
<>...</> 是 <Fragment>...</Fragment> 的简写,渲染出来不会产生额外 DOM 节点,等价于 Vue 的"透明"多根。
六、注释、原始 HTML 等细节
复制代码function Demo({ html }) {
return (
<div>
{/* 这是 JSX 里的注释,必须包在大括号里 */} {/* Vue 的 v-html 等价物(同样注意 XSS 风险) */}
<div dangerouslySetInnerHTML={{ __html: html }} />
</div>
)
}
React 故意把这个 API 起名叫 dangerouslySetInnerHTML,就是提醒你:像 Vue 的 v-html 一样,会有 XSS 风险,慎用。
七、JSX 的本质(理解这点就通透了)
JSX 只是语法糖,最终会被编译成普通函数调用:
复制代码<h1 className="title">Hello</h1>
// 编译后 ≈
React.createElement('h1', { className: 'title' }, 'Hello')
它返回一个描述 UI 的普通 JS 对象(叫"React 元素")。所以 JSX 能像值一样被赋给变量、放进数组、当函数返回值——这正是 React 灵活性的来源:
复制代码function Demo({ isLoggedIn }) {
// JSX 可以存进变量
const greeting = isLoggedIn ? <p>欢迎回来</p> : <p>请登录</p>
const buttons = ['保存', '取消'].map(t => <button key={t}>{t}</button>) return <div>{greeting}{buttons}</div>
}
在 Vue 里你要靠 v-if/v-for 指令;在 React 里,这些都只是普通的 JS 变量和数组操作。
小结
- JSX = 在 JS 里写 UI,插值用单
{ },里面放表达式。 class → className,:attr="x" → attr={x},style 只收驼峰对象。- class 多条件拼接推荐
clsx,找回 Vue 对象语法的手感。 - 多根用
<>...</>(Fragment),v-html对应dangerouslySetInnerHTML。 - 本质上 JSX 返回普通 JS 对象,所以 UI 可以当变量传来传去。
下一篇讲组件与 Props——看看 React 如何定义组件、如何声明和传递 props。