Vue 中的 JSX:让组件渲染更灵活的正确方式

在日常 Vue 项目中,你可能已经非常熟悉 template 写法:结构清晰、语义明确、直观易读。但当业务进入更复杂的阶段,你会发现:

  • 模板语法存在一定限制
  • 某些 UI 渲染逻辑十分动态
  • 条件/循环/组件嵌套变得越来越难写
  • h 函数(createVNode)看得懂,但自己写非常痛苦

这时,你可能会想:有没有一种方式既能保持 DOM 结构的直观性,又能充分利用 JavaScript 的灵活表达?

答案是:JSX

你可能会问:JSX 不是 React 的东西吗?

是,但 Vue 同样支持 JSX,并且在组件库、动态 UI 控件、高度抽象组件中大量使用。

本文将从三个核心问题带你理解 Vue 中的 JSX:

  1. JSX 的本质是什么?
  2. 为什么需要 JSX,它能解决什么问题?
  3. 在 Vue 中如何优雅地使用 JSX?

h 函数:理解 JSX 的前置知识

Vue 组件的 template 最终会被编译为一个 render 函数 ,render 函数会返回 虚拟 DOM(VNode)

也就是说,下面这段模板:

css 复制代码
<h3>你好</h3>

最终会变成类似这样的 JavaScript:

csharp 复制代码
h('h3', null, '你好')

也就是说:

h 函数 = 手写虚拟 DOM 的入口
JSX = h 函数的语法糖


为什么需要 JSX?来看一个真实例子

假设我们做一个动态标题组件 <Heading />,它根据 level 动态渲染 <h1> ~ <h6>

如果使用 template,你可能写成这样:

xml 复制代码
<h1 v-if="level === 1"><slot /></h1>
<h2 v-else-if="level === 2"><slot /></h2>
...
<h6 v-else-if="level === 6"><slot /></h6>

非常冗余、难拓展、维护成本高。

使用 h 函数可以简化为:

javascript 复制代码
import { h, defineComponent } from 'vue'

export default defineComponent({
  props: { level: Number },
  setup(props, { slots }) {
    return () => h('h' + props.level, {}, slots.default())
  }
})

但写 h 函数并不优雅,标签、属性、事件都要自己构造。

这时 JSX 就来了。


在 Vue 中使用 JSX

① 安装 JSX 插件(Vite 项目)

bash 复制代码
npm install @vitejs/plugin-vue-jsx -D

② 在 vite.config.js 中启用

javascript 复制代码
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'

export default {
  plugins: [vue(), vueJsx()]
}

③ 使用 JSX 改写 Heading 组件

javascript 复制代码
import { defineComponent } from 'vue'

export default defineComponent({
  props: { level: Number },
  setup(props, { slots }) {
    const Tag = 'h' + props.level
    return () => <Tag>{slots.default()}</Tag>
  }
})

是不是比手写 h 爽太多了?
结构依然直观,但不受 template 语法局限。


JSX 的核心能力:灵活、动态、纯 JavaScript

举个再明显的例子:Todo 列表

javascript 复制代码
import { defineComponent, ref } from 'vue'

export default defineComponent({
  setup() {
    const title = ref('')
    const todos = ref([])

    const addTodo = () => {
      if (title.value.trim()) {
        todos.value.push({ title: title.value })
        title.value = ''
      }
    }

    return () => (
      <div>
        <input vModel={title.value} />
        <button onClick={addTodo}>添加</button>
        <ul>
          {todos.value.length
            ? todos.value.map(t => <li>{t.title}</li>)
            : <li>暂无数据</li>}
        </ul>
      </div>
    )
  }
})

可以看到:

模板语法 JSX 对应写法
v-model vModel={value}
@click onClick={fn}
v-for array.map()
v-if 三元 / if 表达式

本质是 JavaScript,可以随意写逻辑。


JSX vs Template:应该如何选择?

对比点 template JSX
可读性 强,结构清晰 视业务复杂度而定
动态表达能力 较弱(语法受限) 非常强(JS 语法全支持)
编译优化 优秀,可静态提升 不如 template 友好
适用场景 普通业务 UI 高动态逻辑、组件库、渲染函数场景

一句话总结选择策略:

业务组件优先 template
高动态组件或组件库优先 JSX


JSX 并不是来替代 template 的,而是:

当 template 无法优雅表达渲染逻辑时,JSX 给你打开了一扇窗。

  • 它让组件变得更灵活
  • 它让写 render 函数变得不再痛苦
  • 它让 Vue 在复杂组件抽象层面更加强大

掌握 JSX,是从"会写 Vue"向"会设计 Vue 组件"的关键一步。

相关推荐
在泡泡里2 小时前
前端规范【四】eslint(antfu)、lefthook、commitlint
前端
烛阴2 小时前
Python 几行代码,让你的照片秒变艺术素描画
前端·python
Jolyne_2 小时前
如何实现无感刷新Token
前端
用户4099322502122 小时前
Vue3响应式系统的底层原理与实践要点你真的懂吗?
前端·ai编程·trae
apollo_qwe2 小时前
Vue 权限控制神技!自定义 auth 指令优雅实现按钮级权限管理
vue.js·架构
qq_479875432 小时前
RVO和移动语义
前端·算法
加菲喵2 小时前
深度解析:在vue3中使用自定义Hooks
前端
hxmmm3 小时前
js中生成器和迭代器
前端
阿登林3 小时前
Vue面试项目经验分享:如何专业展示技术能力与解决问题
vue.js·经验分享·面试