
比较 Vue 3 和 React,模板和 JSX 是绕不开的话题。很多讨论会停在一个很表面的结论上:Vue 更像 HTML,React 更像 JavaScript。这个说法没错,但太粗。真正影响开发体验的不是“看起来像不像 HTML”,而是框架把 UI 表达式、编译优化、团队约束和组件边界分别放在了哪里。
Vue 3 的默认写法是单文件组件,也就是 .vue 文件。一个组件里通常有 <template>、<script setup> 和 <style>。React 的默认写法通常是一个 JavaScript 或 TypeScript 文件,组件函数返回 JSX。两者都能描述 UI,也都能写复杂应用,但它们对“模板应该多自由”这件事的答案不一样。
Vue 更倾向于提供一套 HTML-based template syntax,让大多数 UI 结构保持在接近 HTML 的语义里。React 则把 UI 视为 JavaScript 表达式的一部分,JSX 本身只是语法扩展,最终还是 JavaScript。
这个差异看起来只是写法,实际会一路影响到代码审查、性能优化、团队新人上手、组件抽象方式,甚至影响你如何拆分文件。

Vue 3 的模板语法是声明式的。你在模板里写 v-if、v-for、:class、@click、v-model,这些指令都带有明确语义。比如:
<template>
<section class="user-card" :class="{ active: user.active }">
<h2>{{ user.name }}</h2>
<button @click="toggleActive">
{{ user.active ? '停用' : '启用' }}
</button>
</section>
</template>这段代码的好处不是“短”,而是 UI 结构非常稳定。模板里能写表达式,但通常不会鼓励你塞一大段业务逻辑。条件、循环、事件、属性绑定都有固定写法,团队成员阅读时很容易找到重点。
对中后台、管理系统、表单页来说,这种稳定性很重要。很多业务页面并不需要特别激进的抽象能力,需要的是可读、可维护、接手成本低。Vue 模板在这方面有天然优势:HTML 结构像 HTML,行为绑定有统一指令,样式通常也在同一个 SFC 里就近维护。
Vue 单文件组件也降低了组件边界的歧义。你打开一个 .vue 文件,大概率能同时看到结构、逻辑和样式。Vue 官方文档也解释过,SFC 并不是简单地把 HTML、CSS、JS 混在一起,而是把同一个组件的相关关注点放在一个文件里。这一点对组件化开发非常关键。传统的“按技术类型拆文件”适合页面较少的时代;现代前端更常见的问题是组件数量多、交互密度高,把同一个组件的结构、状态、样式分散到多个文件里,反而会增加定位成本。
当然,模板不是没有代价。Vue 模板的表达能力受模板语法限制。虽然模板里可以写 JavaScript 表达式,但不能像 JSX 那样随意使用完整的 JavaScript 语句。复杂渲染逻辑最好提前放到计算属性、函数或子组件里。这既是限制,也是约束。对团队来说,限制有时是好事,因为它逼着开发者把复杂逻辑从视图结构里拿出去。
React 的 JSX 不是模板语言,而是 JavaScript 的语法扩展。React 官方文档也明确说,JSX 是一种用于表示 markup 的语法扩展,React 组件可以通过它描述 UI。它看起来像 HTML,但本质上仍然进入 JavaScript 的表达式体系。
所以 React 里可以这样写:
export default function UserList({ users, onSelect }) {
return (
<ul>
{users
.filter(user => user.visible)
.map(user => (
<li key={user.id} onClick={() => onSelect(user)}>
{user.name}
</li>
))}
</ul>
)
}这里没有 v-for,没有 v-if,条件和循环就是 JavaScript。你可以用 map,可以用三元表达式,可以提前声明变量,也可以把一段 JSX 赋给变量再组合。React 的表达力来自 JavaScript 本身。
这对复杂组件库、设计系统、跨端组件、可配置渲染器来说非常有用。比如一个表格组件需要根据 column 配置生成表头、单元格、筛选器和操作区,JSX 的灵活性会非常自然。你可以把渲染逻辑当函数传递,把一段 UI 当参数组合,也可以用普通 JavaScript 把复杂结构拆开。
但表达能力强也意味着约束弱。React 代码写得好,可以非常清晰;写得差,也很容易把业务判断、数据转换、事件副作用、样式拼接全部塞在 return 里。JSX 不是问题,问题是 JSX 给了开发者足够自由,而自由需要工程规范兜底。
这就是为什么很多 React 团队会强调组件拆分、render helper、hooks 规则、eslint、TypeScript 类型约束,以及对 useMemo、useCallback 的合理使用。不是 React 天生复杂,而是 React 把很多边界交给团队自己决定。
模板和 JSX 的差异,还有一个常被忽略的点:编译器能看懂多少东西。
Vue 模板因为语法受控,编译器可以提前分析模板结构。Vue 3 官方渲染机制文档提到,Vue 会把模板编译成渲染函数,并通过静态提升、patch flag、树结构打平等优化方式减少运行时成本。简单说,Vue 可以在编译阶段知道哪些节点是静态的,哪些节点有动态 class,哪些节点只有文本会变,哪些节点需要事件监听。
这就是模板语法带来的工程收益。你牺牲了一部分任意 JavaScript 的自由,换来编译器更容易理解你的 UI 结构。
React 的 JSX 也会被编译,但它本质上仍然是 JavaScript 表达式。React 当然也有自己的优化路线,比如 React Compiler 已经成为 React 生态里非常重要的方向;但从传统 JSX 模型看,框架默认并不像 Vue 模板那样通过受控模板语法拿到大量静态结构信息。React 更依赖组件重新执行、虚拟 DOM 对比、开发者拆分组件、memo 化和新编译能力来优化。
这不是谁先进谁落后的问题,而是路线不同。Vue 的默认路径更强调“模板受控,所以编译器更容易帮你”;React 的默认路径更强调“UI 就是 JavaScript,所以表达能力和组合能力优先”。
在真实团队里,技术选择不能只看高手能写出什么,也要看普通成员每天会写出什么。
Vue 模板的好处是下限比较稳。一个刚加入项目的人,只要熟悉 HTML、CSS、基础 JavaScript,再掌握 Vue 指令,就能比较快读懂页面。模板语法限制了过度自由,代码审查时也容易发现问题:模板太长就拆组件,表达式太复杂就放到 computed,事件处理太重就抽函数。
React JSX 的上限很高。经验丰富的团队可以用它写出高度抽象、可组合、类型严密的组件体系。但如果团队没有统一规范,JSX 也容易变成“什么都能写,所以什么都写进去”。一个组件里既有请求数据,又有权限判断,又有渲染分支,又有样式对象,又有若干内联函数,后期维护会很痛苦。
所以我更愿意这样判断:Vue 模板更适合希望框架给出清晰边界的团队;React JSX 更适合能用工程规范管理自由度的团队。
如果团队里前端水平差异比较大,Vue 的模板和 SFC 通常更容易统一风格。如果团队有成熟的组件库、设计系统、TypeScript 基础和代码审查流程,React JSX 的自由度会带来更强的抽象能力。
网上有两种常见误解。
第一种是说 Vue 模板不如 JSX 灵活,所以 Vue 不适合复杂项目。这个结论不成立。Vue 3 支持渲染函数,也支持 JSX,只是默认推荐模板。复杂项目的关键不是 UI 表达语法,而是状态边界、模块拆分、组件设计、工程治理和测试策略。模板一样可以支撑大型应用,只要架构设计合理。
第二种是说 React JSX 太自由,所以代码一定难维护。这个结论也不成立。JSX 的自由度确实高,但成熟团队可以通过 lint、类型、组件分层和设计规范把它约束住。很多大型前端项目选择 React,不是因为 JSX 看起来更酷,而是因为 React 的组件模型、生态系统和 JavaScript 表达能力能匹配它们的工程需求。
真正的问题不是模板和 JSX 谁更“高级”,而是你希望框架替你规定多少东西。
Vue 的模板像是一条铺好的路。它告诉你条件怎么写、循环怎么写、事件怎么绑、双向绑定怎么处理。React 的 JSX 更像是一块开放场地。你可以搭出非常漂亮的结构,也可能搭成一片混乱。Vue 更强调约定和编译器协作,React 更强调 JavaScript 能力和组合自由。
如果你的项目以页面交付为主,比如后台管理、运营系统、配置平台、数据报表,Vue 模板通常会更省心。结构清楚,约束明确,SFC 开发体验完整,业务同学接手成本也低。
如果你的项目需要大量动态渲染逻辑,比如复杂低代码渲染器、跨端组件体系、强配置化设计系统、深度依赖函数组合的 UI 架构,React JSX 的优势会更明显。因为在这些场景里,UI 本身经常就是 JavaScript 数据结构和函数组合的结果。
如果团队还在成长阶段,不要盲目追求自由度。自由不是免费的,越自由越需要规范。反过来,如果团队已经有强工程能力,也不要低估 Vue 模板。模板的约束能让很多普通页面写得更稳定,编译器还能从中拿到更多优化信息。
Vue 3 把一部分复杂度交给模板编译器和框架约定。你按模板规则写,框架就能更明确地分析结构、追踪动态部分、组织更新。React 把更多复杂度留在 JavaScript 里。你获得更强的表达能力,也承担更多代码组织责任。
所以比较模板和 JSX,不应该问“哪个写起来更像 HTML”。更有价值的问题是:你的团队需要更多约束,还是更多表达自由?你的 UI 逻辑主要是页面结构,还是高度动态的函数组合?你的工程规范能不能支撑 JSX 的自由度?你的业务是否更受益于 Vue 模板的清晰边界和编译优化?
把这些问题想清楚,比争论模板和 JSX 谁先进更有意义。
比如一个列表里同时包含空状态、加载状态和正常数据,Vue 模板通常会把状态分支直接放在结构里:
<script setup>
defineProps({
loading: Boolean,
users: Array
})
</script>
<template>
<section class="user-panel">
<p v-if="loading">加载中...</p>
<p v-else-if="users.length === 0">暂无用户</p>
<ul v-else>
<li v-for="user in users" :key="user.id">
<span>{{ user.name }}</span>
<strong v-if="user.vip">VIP</strong>
</li>
</ul>
</section>
</template>React 里同样逻辑更常见的是用 JavaScript 提前组织分支:
function UserPanel({ loading, users }) {
if (loading) {
return <section className="user-panel">加载中...</section>
}
if (users.length === 0) {
return <section className="user-panel">暂无用户</section>
}
return (
<section className="user-panel">
<ul>
{users.map(user => (
<li key={user.id}>
<span>{user.name}</span>
{user.vip && <strong>VIP</strong>}
</li>
))}
</ul>
</section>
)
}如果 UI 分支很多,React 也可以把中间 JSX 拆成变量:
function UserPanel({ loading, users }) {
let content
if (loading) {
content = <p>加载中...</p>
} else if (users.length === 0) {
content = <p>暂无用户</p>
} else {
content = users.map(user => <UserRow key={user.id} user={user} />)
}
return <section className="user-panel">{content}</section>
}这几个例子能看出差异:Vue 模板更像在 HTML 结构上加声明式指令;React JSX 更像用 JavaScript 控制返回哪段 UI。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。