テクノロジー
やってみた

Vue3の実験的な新機能 「Reactivity Transform」 使ってみた

TypeScript

Vue

Vue3

こんにちは橋本です。
今日は 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」の使い方を紹介させていただきました
大変便利な機能ですが、あくまで実験的な機能なので、正式採用されるまでは自己責任での使用をお願いします

author img for akfmi

akfmi

前の記事へ

次の記事へ

一覧へ戻る
PAGE TOP