Vue 使用 JSX 开发配置
HumphreyDanvue3 使用 ts 开发,天然支持 tsx 开发.本文记录下如何在 bun + vitejs 环境下配置 tsx
1、添加依赖
1 2
   | bun add vue vue-router vuetify bun add -D @mdi/font @types/node @vitejs/plugin-vue @vitejs/plugin-vue-jsx typescript vite vue-tsc
   | 
 
2、配置 tsconfig.json
主要是打开 jsx 支持
1 2 3 4
   | { 	"jsx": "preserve",     "jsxImportSource": "vue", }
  | 
 
完整配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
   | {   "compilerOptions": {     "target": "ES2020",     "useDefineForClassFields": true,     "module": "ESNext",     "lib": [       "ES2020",       "DOM",       "DOM.Iterable"     ],     "skipLibCheck": true,          "moduleResolution": "bundler",     "allowImportingTsExtensions": true,     "allowSyntheticDefaultImports": true,     "resolveJsonModule": true,     "isolatedModules": true,     "noEmit": true,          "strict": true,     "noUnusedLocals": true,     "noUnusedParameters": true,     "noFallthroughCasesInSwitch": true,     "jsx": "preserve",     "jsxImportSource": "vue",     "paths": {       "@/*": [         "./src/*"       ],       "~/*": [         "./public/*"       ]     }   },   "include": [     "src/**/*.ts",     "src/**/*.d.ts",     "src/**/*.tsx",     "src/**/*.vue",     "vite.config.ts",   ] }
  | 
 
3、配置 vite.config.ts
1 2 3 4
   | ++ import vue from "@vitejs/plugin-vue"; ++ import vueJsx from '@vitejs/plugin-vue-jsx' export default defineConfig(async () => ({ ++  plugins: [vue(), vueJsx())],
   | 
 
如此就可以直接使用 tsx 文件进行开发.
4、由于 vscode 插件对 tsx 支持不完善, 导致 onClick 等事件识别不了而报 lint 错误,所以手动添加下类型说明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
   | import { VNodeProps } from 'vue'
  type EventModifiers = {   capture?: boolean   once?: boolean   passive?: boolean   stop?: boolean   prevent?: boolean   self?: boolean }
 
  type EventHandler<T = Event> = ((event: T) => void) | {   handler: (event: T) => void   modifiers: EventModifiers }
  export type ModifierKey = 'stop' | 'prevent' | 'capture' | 'self' | 'once' | 'passive'
  export type WithModifiers<T> = T & {   [key in `_${ModifierKey}`]: WithModifiers<T> }
  export type EventHandlerWithModifiers<T extends Function> = WithModifiers<T>
  declare module 'vue' {   interface HTMLAttributes {          onClick?: EventHandler<MouseEvent>     onDblclick?: EventHandler<MouseEvent>     onMousedown?: EventHandler<MouseEvent>     onMouseup?: EventHandler<MouseEvent>     onMouseover?: EventHandler<MouseEvent>     onMousemove?: EventHandler<MouseEvent>     onMouseout?: EventHandler<MouseEvent>     onContextmenu?: EventHandler<MouseEvent>
           onKeydown?: EventHandler<KeyboardEvent>     onKeypress?: EventHandler<KeyboardEvent>     onKeyup?: EventHandler<KeyboardEvent>
           onChange?: EventHandler<Event>     onInput?: EventHandler<Event>     onSubmit?: EventHandler<Event>     onReset?: EventHandler<Event>
           onFocus?: EventHandler<FocusEvent>     onBlur?: EventHandler<FocusEvent>
           onScroll?: EventHandler<UIEvent>     onWheel?: EventHandler<WheelEvent>     onDrag?: EventHandler<DragEvent>     onDragstart?: EventHandler<DragEvent>     onDragend?: EventHandler<DragEvent>     onDragenter?: EventHandler<DragEvent>     onDragleave?: EventHandler<DragEvent>     onDragover?: EventHandler<DragEvent>     onDrop?: EventHandler<DragEvent>   }
    interface ComponentCustomProps extends HTMLAttributes {                                   [event: `on${string}`]: (...args: any[]) => void   } }
  | 
 
另外如果想在项目中使用 mdx, 需要如下配置
1、添加依赖 
1 2
   | bun add @mdx-js/vue bun add -D @mdx-js/rollup @mdx-js/vue @types/mdx
   | 
 
2、配置 vite.config.ts
1 2 3 4 5 6 7 8 9 10 11
   | ++ import mdx from '@mdx-js/rollup' export default defineConfig(async () => ({   plugins: [vue(), vueJsx(),  ++	mdx({ ++	    jsxImportSource: 'vue', ++	    jsxRuntime: 'automatic', // 或 'automatic' ++	    providerImportSource: '@mdx-js/vue', // 使用 Vue 运行时 ++	    remarkPlugins: [], ++	    rehypePlugins: [] 	  })   ],
   | 
 
主要配置 mdx 插件,使用 @mdx-js/vue 来渲染生成 mdx 文件对应的 VNode. 否则就会使用内置的 preact 生成 Component 而报错
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
   | import { defineConfig } from "vite"; import vue from "@vitejs/plugin-vue"; import vueJsx from '@vitejs/plugin-vue-jsx' import mdx from '@mdx-js/rollup' import path from "path" const host = process.env.TAURI_DEV_HOST;
 
  export default defineConfig(async () => ({   plugins: [vue(), vueJsx(), mdx({     jsxImportSource: 'vue',     jsxRuntime: 'automatic',      providerImportSource: '@mdx-js/vue',      remarkPlugins: [],     rehypePlugins: []   })],   resolve: {     alias: {       "@": path.resolve(__dirname, "./src"),       "~": path.resolve(__dirname, "./public"),     },   },            clearScreen: false,      server: {     port: 1420,     strictPort: true,     host: host || false,     hmr: host       ? {         protocol: "ws",         host,         port: 1421,       }       : undefined,     watch: {              ignored: ["**/src-tauri/**"],     },   }, }));
 
  | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   | import { defineComponent } from "vue"; import { VCard, VContainer, VSheet } from "vuetify/components"; import Earth from '~/mdx/Earth.mdx';
  export default defineComponent({   setup() {     return () => (       <VContainer>         <VSheet rounded="lg"></VSheet>         <VCard>           <Earth/>         </VCard>       </VContainer>     )   } })
  |