Vue 3 + TSX (JSX) の環境作成(Vite 使用)
Vue + JSX に興味が出たので試してみることにした。
今回は Vite を使って構築していく。
npm init @vitejs/app vue-tsx --template vue-ts
そのままだと JSX が書けないようなので、プラグインをインストールして設定に追加。
npm i -D @vitejs/plugin-vue-jsx
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
+import vueJsx from '@vitejs/plugin-vue-jsx'
// https://vitejs.dev/config/
export default defineConfig({
- plugins: [vue()]
+ plugins: [vue(), vueJsx()]
})
.vue ファイルを使わず、.tsx ファイルだけを使う場合(後述)は、元からある vue
のプラグインは削除してよい。
template 部分を削除。
script タグを lang="tsx"
に変更。
components プロパティは不要。
setup のreturn を JSX を書き出す関数に変更。
画像ファイルは絶対パスに変更する必要があった。 import がよい(後述)
-<template>
- <img alt="Vue logo" src="./assets/logo.png" />
- <HelloWorld msg="Hello Vue 3 + TypeScript + Vite" />
-</template>
-<script lang="ts">
+<script lang="tsx">
import { defineComponent } from 'vue'
import HelloWorld from './components/HelloWorld.vue'
export default defineComponent({
name: 'App',
- components: {
- HelloWorld
- }
+ setup() {
+ return () => (
+ <>
+ <img alt="Vue logo" src="src/assets/logo.png" />
+ <HelloWorld msg="Hello Vue 3 + TypeScript + Vite" />
+ </>
+ )
+ }
})
</script>
FYI: Options API で書く場合は、render メソッドとして定義
render() {
return (
<>
<img alt="Vue logo" src="src/assets/logo.png" />
<HelloWorld msg="Hello Vue 3 + TypeScript + Vite" />
</>
)
}
追記: 画像は絶対パスではなく import して src に指定するのが正解っぽい
import logo from './assets/logo.png'
// 中略
<img alt="Vue logo" src={logo} />
FYI: style タグが不要な場合は .tsx ファイルにしてもよい(script タグの中身だけ残す)
import { defineComponent } from "vue";
import HelloWorld from "./components/HelloWorld.vue";
export default defineComponent({
name: "App",
components: {
HelloWorld
},
setup() {
// 中略
}
})
追記: .tsx ファイルは Vue Test Utils の対応が不完全らしい。
あとからスタイルを当てたくなったときにリネームしないといけなくなるので、.tsx は避けて全部 .vue ファイル(+ script タグ)にしておくのがよさそうか@click
は onClick
にする
イベントハンドラは関数にする
ref の値には .value
をつける
-<template>
- <button @click="count++">count is: {{ count }}</button>
-</template>
setup: () => {
const count = ref(0)
- return { count }
+ return () => (
+ <button onClick={() => count.value++}>count is: {count.value}</button>
+ )
}
JSX だと HMR が効かず、手動でリロードしないと反映されないので地味にストレスがたまる...
調べたら過去に issue が立っていて修正されてるっぽいけど違うか?
今後のアップデートに期待。v-model はそのまま使えた。
修飾子をつける場合はドットではなくアンダースコアをつけて v-model_lazy=
のようにする
setup() {
const text = ref('')
return () => (
<>
<p>text: {text.value}</p>
<input v-model={text.value} />
</>
)
}
Vite の JSX プラグインの依存元は @vue/babel-preset-jsx
というパッケージで、README では vModel=
となっているが、その書き方だと動作はするものの Vetur 上でエラー表示される。(ちなみに vOn:click
はランタイムエラーになった)
https://github.com/vuejs/jsx
↑間違い
JSX プラグインの依存元は @vue/babel-plugin-jsx
だった。
修飾子は以下のように書くのが正解(上記のアンダースコアでも動作はしている)
<input v-model={val} />
<input v-model={[val, ["modifier"]]} />
<A v-model={[val, "argument", ["modifier"]]} />