Vue.js は Reactivity Transform でさらに進化する
Reactivity Transform とは
Vue 3.2.25 から experimental で実装されている機能です[1]。script setup の defineProps()
などと同様、コンパイラーマクロによってコードを変換する仕組みです。
公式ドキュメントからコードを引用しつつ、主要なポイントを解説したいと思います[2]。
ref の変換
今まで Composition API の ref の値を使用するには毎回 .value
を書く必要がありました。Reactivity Transform の $ref()
を使用すると以下のように .value
なしで値にアクセスしたり再代入できるようになります。
<script setup>
let count = $ref(0)
console.log(count)
function increment() {
count++
}
</script>
<template>
<button @click="increment">{{ count }}</button>
</template>
とてもシンプルで分かりやすいですね。
このコードはコンパイル時に次のように変換されます。
import { ref } from 'vue'
let count = ref(0)
console.log(count.value)
function increment() {
count.value++
}
$ref
以外に $computed
や $shallowRef
なども用意されています。
分割代入
ref のオブジェクトを返すコンポーザブル関数などには、$()
を使用すると分割代入した結果に .value
なしでアクセスできます。
import { useMouse } from '@vueuse/core'
const { x, y } = $(useMouse())
console.log(x, y)
このコードはコンパイル時に次のように変換されます。
import { toRef } from 'vue'
import { useMouse } from '@vueuse/core'
const __temp = useMouse(),
x = toRef(__temp, 'x'),
y = toRef(__temp, 'y')
console.log(x.value, y.value)
ref に戻す
.value
なしでアクセスできるのは便利ですが、ref として扱いたい場合もあります。
function trackChange(x: Ref<number>) {
watch(x, (x) => {
console.log('x changed!')
})
}
let count = $ref(0)
trackChange(count) // doesn't work!
このコードの trackChange
は Ref<number>
を引数にとりますが、以下のようにコンパイルされるのでうまく動きません。
let count = ref(0)
trackChange(count.value)
この場合は count
変数を $$()
でラップすることで、コンパイル後も ref のままになります。
let count = $ref(0)
- trackChange(count)
+ trackChange($$(count))
↓
let count = ref(0)
trackChange(count)
TypeScript で使う
型定義ファイルに以下を追加することで、マクロの型情報がグローバルに登録され、型推論やコード補完などが有効になります。
/// <reference types="vue/macros-global" />
オプトイン手順
2022 年 2 月現在、Reactivity Transform はデフォルトでは無効になっているので、有効化するための設定が必要となります。
また、vue@^3.2.25
が必要です。
Vite
@vitejs/plugin-vue@^2.0.0
が必要。
// vite.config.js
export default {
plugins: [
vue({
reactivityTransform: true
})
]
}
公式ドキュメントには vue-cli や webpack + vue-loader 向けの設定もあります。
まとめ
script setup に引き続き、Vue.js のコードがどんどんシンプルになっていきますね。.value
が消えるとだいぶ読みやすくなって良いと思います。一方で $()
や $$()
は直感的でないと感じる人もいそうなので好みが分かれるところでしょうか。
Evan 氏のコメントによると、Q2 にリリースされる Vue 3.3 にて experimental が取れるようなので、それまでは破壊的変更があるかも知れません。
ここのところ、次から次へと新しい機能が Vue.js に取り入れられているので、今後どんな機能が入っていくのか楽しみですね。
Discussion