Skip to content

Commit 08e7e06

Browse files
author
obsidian
committed
vault backup: 2025-06-30 17:05:46 A source/_posts/Vue 使用 TSX 开发配置.md
Affected files: source/_posts/Vue 使用 TSX 开发配置.md
1 parent b12592a commit 08e7e06

File tree

1 file changed

+259
-0
lines changed

1 file changed

+259
-0
lines changed
Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
---
2+
title: Vue 使用 JSX 开发配置
3+
date: 2025-06-30 12:08
4+
updated: 2025-06-30T12:08:34+08:00
5+
permalink:
6+
top: 0
7+
comments:
8+
copyright: true
9+
tags:
10+
categories:
11+
keywords:
12+
description:
13+
---
14+
vue3 使用 ts 开发,天然支持 tsx 开发.本文记录下如何在 bun + vitejs 环境下配置 tsx
15+
16+
1、添加依赖
17+
18+
```sh
19+
bun add vue vue-router vuetify
20+
bun add -D @mdi/font @types/node @vitejs/plugin-vue @vitejs/plugin-vue-jsx typescript vite vue-tsc
21+
```
22+
23+
2、配置 tsconfig.json
24+
25+
主要是打开 jsx 支持
26+
```json
27+
{
28+
"jsx": "preserve",
29+
"jsxImportSource": "vue",
30+
}
31+
```
32+
33+
完整配置
34+
```json
35+
{
36+
"compilerOptions": {
37+
"target": "ES2020",
38+
"useDefineForClassFields": true,
39+
"module": "ESNext",
40+
"lib": [
41+
"ES2020",
42+
"DOM",
43+
"DOM.Iterable"
44+
],
45+
"skipLibCheck": true,
46+
/* Bundler mode */
47+
"moduleResolution": "bundler",
48+
"allowImportingTsExtensions": true,
49+
"allowSyntheticDefaultImports": true,
50+
"resolveJsonModule": true,
51+
"isolatedModules": true,
52+
"noEmit": true,
53+
/* Linting */
54+
"strict": true,
55+
"noUnusedLocals": true,
56+
"noUnusedParameters": true,
57+
"noFallthroughCasesInSwitch": true,
58+
"jsx": "preserve",
59+
"jsxImportSource": "vue",
60+
"paths": {
61+
"@/*": [
62+
"./src/*"
63+
],
64+
"~/*": [
65+
"./public/*"
66+
]
67+
}
68+
},
69+
"include": [
70+
"src/**/*.ts",
71+
"src/**/*.d.ts",
72+
"src/**/*.tsx",
73+
"src/**/*.vue",
74+
"vite.config.ts",
75+
]
76+
}
77+
```
78+
79+
3、配置 vite.config.ts
80+
81+
```diff
82+
++ import vue from "@vitejs/plugin-vue";
83+
++ import vueJsx from '@vitejs/plugin-vue-jsx'
84+
export default defineConfig(async () => ({
85+
++ plugins: [vue(), vueJsx())],
86+
```
87+
88+
如此就可以直接使用 tsx 文件进行开发.
89+
90+
4、由于 vscode 插件对 tsx 支持不完善, 导致 onClick 等事件识别不了而报 lint 错误,所以手动添加下类型说明
91+
```ts
92+
import { VNodeProps } from 'vue'
93+
// 定义修饰符类型
94+
type EventModifiers = {
95+
capture?: boolean
96+
once?: boolean
97+
passive?: boolean
98+
stop?: boolean
99+
prevent?: boolean
100+
self?: boolean
101+
}
102+
103+
// 扩展事件处理器类型
104+
type EventHandler<T = Event> = ((event: T) => void) | {
105+
handler: (event: T) => void
106+
modifiers: EventModifiers
107+
}
108+
109+
export type ModifierKey = 'stop' | 'prevent' | 'capture' | 'self' | 'once' | 'passive'
110+
111+
export type WithModifiers<T> = T & {
112+
[key in `_${ModifierKey}`]: WithModifiers<T>
113+
}
114+
115+
export type EventHandlerWithModifiers<T extends Function> = WithModifiers<T>
116+
117+
declare module 'vue' {
118+
interface HTMLAttributes {
119+
// 鼠标事件
120+
onClick?: EventHandler<MouseEvent>
121+
onDblclick?: EventHandler<MouseEvent>
122+
onMousedown?: EventHandler<MouseEvent>
123+
onMouseup?: EventHandler<MouseEvent>
124+
onMouseover?: EventHandler<MouseEvent>
125+
onMousemove?: EventHandler<MouseEvent>
126+
onMouseout?: EventHandler<MouseEvent>
127+
onContextmenu?: EventHandler<MouseEvent>
128+
129+
// 键盘事件
130+
onKeydown?: EventHandler<KeyboardEvent>
131+
onKeypress?: EventHandler<KeyboardEvent>
132+
onKeyup?: EventHandler<KeyboardEvent>
133+
134+
// 表单事件
135+
onChange?: EventHandler<Event>
136+
onInput?: EventHandler<Event>
137+
onSubmit?: EventHandler<Event>
138+
onReset?: EventHandler<Event>
139+
140+
// 焦点事件
141+
onFocus?: EventHandler<FocusEvent>
142+
onBlur?: EventHandler<FocusEvent>
143+
144+
// 其他事件
145+
onScroll?: EventHandler<UIEvent>
146+
onWheel?: EventHandler<WheelEvent>
147+
onDrag?: EventHandler<DragEvent>
148+
onDragstart?: EventHandler<DragEvent>
149+
onDragend?: EventHandler<DragEvent>
150+
onDragenter?: EventHandler<DragEvent>
151+
onDragleave?: EventHandler<DragEvent>
152+
onDragover?: EventHandler<DragEvent>
153+
onDrop?: EventHandler<DragEvent>
154+
}
155+
156+
interface ComponentCustomProps extends HTMLAttributes {
157+
// 这里可以添加组件特定的props类型
158+
// [event: string]: ((any) => any | {
159+
// [string]?: (any) => any
160+
// modifiers: EventModifiers
161+
// });
162+
// or this
163+
[event: `on${string}`]: (...args: any[]) => void
164+
}
165+
}
166+
```
167+
168+
---
169+
另外如果想在项目中使用 mdx, 需要如下配置
170+
171+
1、添加依赖
172+
```sh
173+
bun add @mdx-js/vue
174+
bun add -D @mdx-js/rollup @mdx-js/vue @types/mdx
175+
```
176+
2、配置 vite.config.ts
177+
```diff
178+
++ import mdx from '@mdx-js/rollup'
179+
export default defineConfig(async () => ({
180+
plugins: [vue(), vueJsx(),
181+
++ mdx({
182+
++ jsxImportSource: 'vue',
183+
++ jsxRuntime: 'automatic', // 或 'automatic'
184+
++ providerImportSource: '@mdx-js/vue', // 使用 Vue 运行时
185+
++ remarkPlugins: [],
186+
++ rehypePlugins: []
187+
})
188+
],
189+
```
190+
191+
主要配置 mdx 插件,使用 `@mdx-js/vue` 来渲染生成 mdx 文件对应的 VNode. 否则就会使用内置的 `preact` 生成 Component 而报错
192+
193+
```ts
194+
import { defineConfig } from "vite";
195+
import vue from "@vitejs/plugin-vue";
196+
import vueJsx from '@vitejs/plugin-vue-jsx'
197+
import mdx from '@mdx-js/rollup'
198+
import path from "path"
199+
const host = process.env.TAURI_DEV_HOST;
200+
201+
// https://vitejs.dev/config/
202+
export default defineConfig(async () => ({
203+
plugins: [vue(), vueJsx(), mdx({
204+
jsxImportSource: 'vue',
205+
jsxRuntime: 'automatic', // 或 'automatic'
206+
providerImportSource: '@mdx-js/vue', // 使用 Vue 运行时
207+
remarkPlugins: [],
208+
rehypePlugins: []
209+
})],
210+
resolve: {
211+
alias: {
212+
"@": path.resolve(__dirname, "./src"),
213+
"~": path.resolve(__dirname, "./public"),
214+
},
215+
},
216+
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
217+
//
218+
// 1. prevent vite from obscuring rust errors
219+
clearScreen: false,
220+
// 2. tauri expects a fixed port, fail if that port is not available
221+
server: {
222+
port: 1420,
223+
strictPort: true,
224+
host: host || false,
225+
hmr: host
226+
? {
227+
protocol: "ws",
228+
host,
229+
port: 1421,
230+
}
231+
: undefined,
232+
watch: {
233+
// 3. tell vite to ignore watching `src-tauri`
234+
ignored: ["**/src-tauri/**"],
235+
},
236+
},
237+
}));
238+
239+
```
240+
241+
242+
```tsx
243+
import { defineComponent } from "vue";
244+
import { VCard, VContainer, VSheet } from "vuetify/components";
245+
import Earth from '~/mdx/Earth.mdx';
246+
247+
export default defineComponent({
248+
setup() {
249+
return () => (
250+
<VContainer>
251+
<VSheet rounded="lg"></VSheet>
252+
<VCard>
253+
<Earth/>
254+
</VCard>
255+
</VContainer>
256+
)
257+
}
258+
})
259+
```

0 commit comments

Comments
 (0)