在 Vue 中使用 JSX
概述
JSX 就是 JavaScript XML, 是 XML 格式的代码, 但是背后会转换为 JS 代码. 本质是虚拟 DOM 的创建代码. 可以视为语法糖.
在 Vue 中使用 JSX 需要几个步骤:
- 安装必要插件
@vitejs/plugin-vue-jsx, 配置vite.config.ts. - 使用
JSX, 有两个形式:- 直接使用
.tsx文件 (如同react). - 使用
.vue文件, 在其中使用lang="tsx"的<script>.
- 直接使用
- 使用
JSX语法. 是否使用setup是的使用JSX的方式略有不同.
也可以使用
lang="js", 但不支持类型.
详细步骤
使用 vue@latest 向导会提示安装 jsx 插件, 并做好配置.
如果需要自行安装:
npm install --save-dev @vitejs/plugin-vue-jsx
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
export default defineConfig({
plugins: [
vue(),
vueJsx(), // 使 Vite 支持 JSX
],
});
然后就可以使用 JSX
直接使用 .tsx 文件
直接创建 .tsx 文件, 将其视为一个模块, 直接导出 JSX 即可.
export default () => <div>...</div>
也可以使用
defineComponent, 但是事实上没必要.export default defineComponent({ render() { return <div>...</div> } })既然使用
tsx, 简洁一点最好.
也可以导出 render 函数. 实际上就是一个返回 JSX 的函数. 如果使用对象语法, 那么就必须注明 render 函数名.
export default function render() {
return <div>...</div>
}
或者
export default {
render: () => <div>...</div>
}
暂时还不支持
react中类语法来创建组件的用法.Vue是基于函数的组件和模板语法的.
使用 .vue 文件
使用 .vue 文件, 与传统用法类似.
- 使用
<template>定义模板. 但是在模板中可以直接使用<script>中定义的组件 (返回JSX的函数). - 使用
<script lang="tsx">来编写脚本, 依旧支持setup语法 (更简洁). - 使用
<style>来定义样式.
jk 依旧不推荐使用
defineComponent({})来定义组件.
<template>
<AppComponent></AppComponent>
</template>
<script lang="tsx" setup>
const AppComponent = () => <div></div>
</script>
其实直接使用
.tsx文件更简洁.
总结一下
使用 JSX, 核心是使用某个函数返回 JSX 代码, 作为页面模板进行渲染. 但是有函数式与对象式两种形式 (组件).
函数式简洁, 但是对生命周期等模块支持不好.
所以还是推荐使用对象式来定义. 例如:
export default defineComponent({
setup() {
onMounted(() => {
console.log('加载完成')
})
const v = ref<string>()
watch(v, (nV?: string, oV?: string) => {
console.log(`watch: v; oldValue = ${ oV }, newValue = ${ nV }`)
})
return () => (
<div >
<ElInput v-model={v.value}></ElInput>
</div>
)
}
})
使用样式
使用样式分为两种情况
.tsx模式下, 定义单独的 样式文件. 例如xxx.module.scss. 推荐模块化的语法..vue模式下,<style></style>来定义样式, 也可以使用模块化语法. 使用时<style module="styleName" lang="scss"></style>.<script>中使用useCssModule()方法:const style = useCssModule('styleName')来引用样式.- 使用模块化后, 不需要考虑
scoped了.