在 Vue 3 中使用 JSX 时,你可能会遇到 React is not defined
和 h is not defined
的错误。这些错误通常是因为 JSX 转换需要知道如何创建 VNode(Vue 的虚拟节点),并且默认情况下 JSX 是为 React 设计的。
为了解决这个问题,你需要做以下几步:
1. 安装必要的插件
如果你使用的是 Babel,确保你已经安装了 @vue/babel-preset-jsx
。
npm install @vue/babel-preset-jsx --save-dev
或者,如果你使用的是 Vite 或 Vue CLI(它内部使用了 Vite),那么 JSX 的支持应该已经内置了。
2. 配置 Babel
在你的 Babel 配置中(例如 .babelrc
或 babel.config.js
),确保你已经设置了 @vue/babel-preset-jsx
预设。
{ "presets": [ "@vue/cli-plugin-babel/preset", "@vue/babel-preset-jsx" ] }
注意:具体的配置可能会因你的项目设置和其他插件/预设而异。
3. 使用 h
函数
在 Vue 3 中,h
函数是创建 VNode 的推荐方式。当你在 JSX 中使用它时,确保你已经从 vue
导入了它。
import { h } from 'vue'; export default { render() { return <div>{ this.message }</div>; } }
但通常,当你使用 @vue/babel-preset-jsx
时,它会自动为 JSX 注入 h
函数,所以你不需要显式地导入或使用它。
4. 避免使用 React
Vue 和 React 是两个不同的库。在 Vue 代码中,你不应该使用 React
。确保你的代码中没有任何 React
的引用或导入。
5. 确保你的工具链是最新的
有时,这类问题可能是由于使用了过时的工具或插件版本造成的。确保你的 Vue、Babel、Vite 或其他相关工具都是最新的。
按照上述步骤操作后,你应该能够成功地在 Vue 3 中使用 JSX,而不会再遇到 React is not defined
和 h is not defined
的错误。
js项目中jsx的使用
- js项目引入Vue 3 Babel JSX 插件
- 修改vite.config.js
import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import vuejsx from "@vue/babel-plugin-jsx" import path from "path" // https://vitejs.dev/config/ export default defineConfig({ plugins: [vue(),vuejsx({})], resolve:{ alias:{ "@": `${path.resolve(__dirname, './src')}` } }, esbuild: { jsxFactory: 'h', jsxFragment: 'Fragment', jsxInject: "import { h } from 'vue';" } })
这样的话就不会出现React is not defined和h is not defined这两个错误。
- 下面是vite官方关于使用jsx的表述:
.jsx 和 .tsx 文件同样开箱即用。JSX 的转译同样是通过 esbuild,默认为 React 16 风格。期望在 esbuild
中支持 React 17 风格的 JSX 请看 这里。
Vue 用户应使用官方提供的 @vitejs/plugin-vue-jsx 插件,它提供了 Vue 3 特性的支持,包括
HMR,全局组件解析,指令和插槽。
如果不是在 React 或 Vue 中使用 JSX,自定义的 jsxFactory 和 jsxFragment 可以使用 esbuild
选项 进行配置。例如对 Preact:
关键问题就是在这里,我到底是不是vue用户?vue用户应该不需要再做其他的配置了,有点懵逼。
// vite.config.js import { defineConfig } from 'vite' export default defineConfig({ esbuild: { jsxFactory: 'h', jsxFragment: 'Fragment' } })
更多细节详见 esbuild 文档.
你可以使用 jsxInject(这是一个仅在 Vite 中使用的选项)为 JSX 注入 helper,以避免手动导入:
// vite.config.js import { defineConfig } from 'vite' export default defineConfig({ esbuild: { jsxInject: `import React from 'react'` } })
- 支持的用法
就是必须导出,必须用defineComponent 这两点
import { defineComponent } from 'vue' // named exports w/ variable declaration: ok export const Foo = defineComponent({}) // named exports referencing variable declaration: ok const Bar = defineComponent({ render() { return <div>Test</div> }}) export { Bar } // default export call: ok export default defineComponent({ render() { return <div>Test</div> }}) // default export referencing variable declaration: ok const Baz = defineComponent({ render() { return <div>Test</div> }}) export default Baz
Non-supported patterns
// not using `defineComponent` call export const Bar = { ... } // not exported const Foo = defineComponent(...)