在Vue3.0中使用JSX的简单入门

    科技2025-11-06  17

    JSX

    直入正题,vue3 对 jsx 和 ts 的支持更加完善,看一下 vue3 的 jsx 官方文档部分:

    非常的简陋了,但是他给我们指引了 vue3 中 jsx 的 babel 转换插件 jsx-next 。

    感兴趣的可以看一下他的 README,下面开始安装使用一下~

    安装 jsx-next

    实际上 vue-cli 建立的 vue3 项目中已经内置了 jsx 的这个编译插件,如果你不需要自定义配置,是不需要安装就可以即开即用 jsx 的,可谓是非常贴心了。

    安装过程如下:

    yarn add -D @vue/babel-plugin-jsx

    安装后在 package.json 看到目前是 rc 状态,还没有正式发布,我们只是简单体验一下。

    之后在 babel.config.js 内配置该插件:

    module.exports = { // 这是原来的预设,cli 搭建项目就有的 presets: [ '@vue/cli-plugin-babel/preset' ], // 需要配置的插件 plugins: ['@vue/babel-plugin-jsx'] }

    之后就可以使用 jsx 了!

    使用

    建立一个 views/Demo.jsx :

    import { defineComponent, ref } from 'vue' const Demo = defineComponent({ name: 'demo', setup (props) { const input = ref(null) const click = (e) => { console.log(e) console.log(input.value) } return { click, input } }, render () { return ( <> <div>test</div> <button onClick={this.click}>点击</button> <input v-model={this.input} placeholder="啊这"/> </> ) } }) export default Demo

    demo 的大致框架如上所示,不需要在意上面的 demo 写了什么,只需要在意整体的结构如下:

    定义组件

    defineComponent() 定义组件,这是为了使得 ts 和 ide 能进行类型推断,从而获得代码提示功能,在配置路由的时候可选用 () => import() 进行懒加载:

    { path: '/demo', name: 'demo', component: () => import(/* webpackChunkName: "demo" */ '../views/Demo.jsx') }

    注:如果你没有代码提示,那一定是没有使用 defineComponent() ,有了这个东西,你才能获得代码提示。

    异步组件

    我们手写一个异步组件的使用例子:

    import Demo from '../views/Demo' // ...... // 路由 { path: '/async', name: 'async', component: defineAsyncComponent({ // 工厂函数 loader: Async, // 加载异步组件时要使用的组件 loadingComponent: Demo }) }

    这里的 loadingComponent 就是组件 loading 时要显示的内容,而 loader 就是要加载的异步组件。

    建立一个 views/Async.jsx:

    import { defineComponent } from 'vue' const Async = () => new Promise((resolve, reject) => { setTimeout(() => { resolve(defineComponent({ render () { return <div>async component</div> } })) }, 3000) }) export default Async

    这段代码只是把 webpack 给我们的 () => import() 变成手写 Promise 了,在 resolve() 内你可以返回你需要加载的组件,当然我们还要用 defineComponent() 以获得代码提示功能保证 eslint 不报错。

    注:

    loader 的目标组件必须是返回一个 Promise 的函数,使用 () => import() 可以达到相同的效果(他会使用一个 Promise 帮你包裹组件),这里我们为了主动延时才手写了 Promise 。loadingComponent 需要是一个同步组件。

    有关更多异步组件 defineAsyncComponent 的选项可以查看官方文档的中文社区翻译版:defineAsyncComponent

    setup

    定义完组件就是 setup 了,为什么不用 vue2 的 template 呢?那就不是 jsx 了。

    有关这部分该如何使用,请看 官方文档 即可。

    props, name …

    在 defineComponent 组件块内,完全和 vue3 新语法等同,还可以使用 props 对上层传入进行限制、指定,以及使用 name 等关键词:

    const Demo = defineComponent({ name: 'demo', props: { key1: { type: String, required: true } } }

    render

    render 才是 jsx 的核心部分,所有的 jsx 要在此处顶层返回。

    和 react 的函数式相比,在 render 内的 jsx ,你还需要使用 this 取得 setup 阶段返回的值。

    总结

    如果实际体验一下,会发现和 react 的函数式组件还是有天壤之别,Vue 本来就不是为 jsx 而生的,template 它不香吗。

    附:

    官方 Vue3 文档:Vue3 Guide

    民间中文版 Vue3 文档:Vue3 文档

    JSX 插件已经内置到 vue-cli 创建的项目中的 issue :这个已经内置到cli 里面去了?

    更多 Vue JSX 的用法请看官方 babel 插件的 README :Vue 3 Babel JSX 插件

    Processed: 0.010, SQL: 8