Vue3の実験的な新機能 「Reactivity Transform」 使ってみた
こんにちは橋本です。
今日は Vue3 で実験的に実装されている新機能、「Reactivity Transform」を紹介したいと思います
Vue3 の Composition API を使用する上で、リアクティブな変数を作成す る場合には、ref を使用して変数定義を行い、値にアクセスする際には.value プロパティを介してアクセスしていると思います
const name = ref('Tarou')
console.log(name.value)
computed も同様ですね
const firstName = ref('Tarou')
const lastName = ref('Yamada')
const fullName = computed(() => firstName.value + lastName.value)
console.log(fullName.value)
これ、正直だるいですよね
エディタで補完がかかるとはいえ、毎回.value 経由でアクセスするのは面倒です
コードも見た目ゴチャゴチャするので、ぶっちゃけ微妙ですよね
「どうせ.vue ファイルコンパイルするんだから、コンパイラ側でよしなにやってくれればいいのに…」
そんな願望を叶える機能が、今回ご紹介する「Reactivity Transform」です
「Reactivity Transform」を使用すると、.value を使用せず値にアクセスできるようになります
まずは実行環境の作成からやっていきましょう
実行環境の作成
create-vue コマンドを使用して、vue3 プロジェクトを作成します
今回は TypeScript を使用する前提で進めますので、TypeScript を有効にしてください
yarn create vue
yarn create v1.22.18
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
[4/4] 🔨 Building fresh packages...
success Installed "create-vue@3.3.4" with binaries:
- create-vue
Vue.js - The Progressive JavaScript Framework
✔ Project name: … sample
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit Testing? … No / Yes
✔ Add Cypress for both Unit and End-to-End testing? … No / Yes
✔ Add ESLint for code quality? … No / Yes
Scaffolding project in /...
Done. Now run:
cd sample
yarn
yarn dev
✨ Done in 47.28s.
Reactivity Transform を有効にするためには、vite.config.ts に以下を追記します
plugins: [
vue({
reactivityTransform: true,
}),
],
次に、env.d.ts に以下を追記します(TypeScript を使用しない場合は、この手順を飛ばしてください)
/// <reference types="vue/macros-global" />
ちなみに、nuxt3 で使用する場合には、nuxt.config.ts に以下を追記します
export default defineNuxtConfig({
...,
experimental: {
reactivityTransform: true,
},
nuxt3 では、TypeScript を使用する場合も、上記の設定を追加するだけで大丈夫です
準備が整ったので、早速使ってみましょう
「Reactivity Transform」を使ってみる
「Reactivity Transform」では、ref の代わりに「$ref」、computedの代わりに「$computed」を使用します
const firstName = $ref('Tarou')
const lastName = $ref('Yamada')
const fullName = $computed(() => firstName + lastName)
console.log(fullName)
「$ref」と「$computed」は実際の関数ではなく、コンパイル時マクロです
上記のコードは実際には以下のような形にコンパイルされます
const firstName = ref('Tarou')
const lastName = ref('Yamada')
const fullName = computed(() => firstName.value + lastName.value)
console.log(fullName.value)
いやー便利ですね($を見ると某ライブラリを思い出して少しモヤッとしますが、気にせずいきましょう)
それでは、もう少し細かく「Reactivity Transform」の使い方を見ていきたいと思います
リアクティブな変数に値を代入したい
リアクティブな変数に値を代入したい場合には、let を使って変数を宣言します
const name = $ref('Tarou')
name = 'Jirou' // Error
let name = $ref('Tarou')
name = 'Jirou' // OK
リアクティブな変数を watch の監視対象にしたい
watch の監視対象にリアクティブな変数を設定したい場合には「$$()」で変数を囲います
「$$()」もコンパイル時マクロで、「$$()」で囲った箇所はコンパイル時に.value が付与されず、ref として扱われます
let name = $ref('Tarou')
watch(name, (newValue) => console.log(newValue)) // Error
watch($$(name), (newValue) => console.log(newValue)) // OK
ちなみに、watchEffect に関してはそのままで大丈夫です
let name = $ref('Tarou')
watchEffect(() => {
console.log($$(name)) // Error
})
watchEffect(() => {
console.log(name) // OK
})
ref()で宣言した変数についても.value を省略して使用したい
ref()を使って宣言した変数についても、$()で囲うことによって、$ref()で宣言した場合と同様に.value の省略を行うことができます
cosnt name = ref('Tarou')
const name2 = $(name)
console.log(name2) // 'Tarou'
その他、「Reactivity Transform」を有効にすると、defineProps マクロも機能強化され、戻り値をリアクティブを保ったまま分割代入することが可能になります
また、分割代入の初期値を設定することで、withDefaults を使用せずに初期値を設定することができます
分割代入が可能になることで、props.を省略できるようになります
Reactivity Transform を使用しない場合
type Props = {
name: string
age?: number
}
const props = withDefaults(defineProps<Props>(), {
age: '20',
})
Reactivity Transform を使用する場合
console.log(props.name, props.age)
const { name, age = 20 } = defineProps<Props>()
console.log(name, age)
まとめ
駆け足でしたが、Vue3 の新機能 「Reactivity Transform」の使い方を紹介させていただきました
大変便利な機能ですが、あくまで実験的な機能なので、正式採用されるまでは自己責任での使用をお願い します