前言
公司之前用Vue2写的老项目需要升级到Vue3,由于本人React写的比较多,对JSX/TSX(以下统称为JSX)比较喜欢,所以在项目新功能开发时,抱着试一试的心态引入了JSX,体验下来还是能满足90%左右的需求,这篇文章就给大家来分享一下在Vue3项目中使用JSX的一些注意事项和心得体会。
环境介绍
项目主要环境及版本:
| package | version |
|---|---|
| vite | @3.2.3 |
| vue | @3.2.41 |
| @vitejs/plugin-vue | @3.2.0 |
| @vitejs/plugin-vue-jsx | @2.1.1 |
开始写一个JSX
在本人一段时间的体验下来,对开发来说体验感最好方式是.vue文件的SFC模式,将lang改为tsx(可能需要配置一下tsconfig)。这种模式的好处在于可以在编写JSX的同时享受Vue的scoped-css提供的编写。
<script lang="tsx">
export default defineComponent({
// ...
})
</script>
<style scoped>
// 这里可以写样式
</style>
但是在这之前还是先聊一下JSX和Vue配合的几种方式:
.jsx + defineComponent
这种方式比较简单,就是采用defineComponent函数创建一个组件,使用setup方法返回组件的DOM结构,这里就不多说了,我编写了一个代码片段,贴出来给大家可以直接在vscode中使用。
{
"vue3 setup template": {
"prefix": "vue-setup",
"body": [
"import { defineComponent, onMounted, ref, reactive } from 'vue';\n",
"export interface ${TM_FILENAME_BASE}Props {}\n",
"export default defineComponent({",
"\tprops: [],",
"\tsetup(props: ${TM_FILENAME_BASE}Props, { emit }) {",
"\t\tonMounted(() => {",
"\t\t\t// ...",
"\t\t})",
"\t\treturn () => (",
"\t\t\t<div></div>",
"\t\t)",
"\t}",
"})"
]
}
}
.jsx + functionalComponent
Vue3是支持函数式组件的,可以在jsx文件中直接默认到处一个函数,返回组件的DOM结构即可,在函数中可以使用Vue3提供的类hooksAPI来创建响应式数据,函数的参数和setup函数的参数是同样的([props, context])。
import {FunctionalComponent} from 'vue'
export interface ComponentProps {
cotnent: string
}
export default (pros, context) => {
return <div>{props.content}</div>
} as FunctionalComponent<ComponentProps>
但是函数式组件在vite中并不支持热重载,所以本人也没有深入使用过,若有知道如何配置函数式组件热重载的小伙伴可以告诉我哦。
.vue + defineComponent
这种方式就是我在一开始的时候提到的方式,也是我使用最多的方式之一,好处在上文已经说过了,这里直接贴出我的vscode代码片段
{
"tsx setup": {
"prefix": "setuptsx",
"body": [
"<script lang=\"tsx\">",
"import { defineComponent, onMounted, reactive, ref } from 'vue';\n",
"export interface ${TM_FILENAME_BASE}Props {}\n",
"export default defineComponent({",
"\tprops: [],",
"\tsetup(props: ${TM_FILENAME_BASE}Props, { emit }) {",
"\t\tonMounted(() => {",
"\t\t\t// ...",
"\t\t})",
"\t\treturn () => (",
"\t\t\t<div></div>",
"\t\t)",
"\t}",
"})",
"</script>"
]
},
}
踩过的坑
这一块内容我会长期更新,大家也可以给我留言,讨论一下jsx和vue配合产生的一些稀奇古怪的issues
1. 组件中返回一个HTML结构会渲染成[Object object]
举个例子:
const renderDiv = () => {
return <div>abc</div>
}
export default defineComponent({
setup() {
return <div>{renderDiv()}</div>
}
})
渲染出的HTML会变成
<div>
<!-- [Object object] -->
</div>