jk's notes
  • 在 Vue 中使用 JSX

在 Vue 中使用 JSX

Vue 官方文档

概述

JSX 就是 JavaScript XML, 是 XML 格式的代码, 但是背后会转换为 JS 代码. 本质是虚拟 DOM 的创建代码. 可以视为语法糖.

在 Vue 中使用 JSX 需要几个步骤:

  1. 安装必要插件 @vitejs/plugin-vue-jsx, 配置 vite.config.ts.
  2. 使用 JSX, 有两个形式:
    1. 直接使用 .tsx 文件 (如同 react).
    2. 使用 .vue 文件, 在其中使用 lang="tsx" 的 <script>.
  3. 使用 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>
    ) 
  }
})

使用样式

使用样式分为两种情况

  1. .tsx 模式下, 定义单独的 样式文件. 例如 xxx.module.scss. 推荐模块化的语法.
  2. .vue 模式下, <style></style> 来定义样式, 也可以使用模块化语法. 使用时
    1. <style module="styleName" lang="scss"></style>.
    2. <script> 中使用 useCssModule() 方法: const style = useCssModule('styleName') 来引用样式.
    3. 使用模块化后, 不需要考虑 scoped 了.
Last Updated:
Contributors: jk