ついにβ版となったVue 3.5の魅力的な新機能をまとめてみた
Vue 3.5 β版のリリースが始まっています!本記事では3.5で追加された新機能などを一足早く動作させてみましたので、個人的に楽しみにしている機能をまとめてみました。
composable
useTemplateRef
テンプレート参照をcomposable
として便利に利用できる関数です。
Vue 3.5より前は以下の様に変数を定義してテンプレート参照を行っていたため、下記のonMounted
の処理をcomposable
としてまとめようとしてもテンプレート参照の変数(下記で言えばtemplateRef
)自体を渡さなければならず、少し扱いづらいところがありました。
<script setup>
import { ref, onMounted } from 'vue'
const templateRef = ref()
onMounted(() => {
templateRef.value.innerText = 'hoge'
})
</script>
<template>
<div ref="templateRef" />
</template>
useTemplateRef
を利用すれば先ほどのmount時にinnerTextを変更する処理をcomposable
内で完結させることが出来ます。
import { useTemplateRef, onMounted } from 'vue'
export function useSampleTemplateRef(key) {
const templateRef = useTemplateRef(key)
onMounted(() => {
templateRef.value.innerText = 'hoge'
})
}
vueファイルは以下の様になります。だいぶスッキリしました。テンプレート参照の変数自体、リアクティブなデータの様に見える部分もあったため、とても良い変更だと思います。
<script setup>
import { useSampleTemplateRef } from './composables'
useSampleTemplateRef('templateRef')
</script>
<template>
<div ref="templateRef" />
</template>
ちなみにTypeScriptの場合は型を付けることも可能です。
// ReadOnly<ShallowRef<HTMLElement | null>>
const templateRef = useTemplateRef<HTMLElement>(key)
useId
ReactのuseIdと同様にフォームの属性などに利用可能な一意のIDを生成する関数です(IDはv:0
のような形式)。
クライアント-サーバ間で一意のIDとなるため、ハイドレーションの際に不一致が発生することなく安定したIDになります。
<script setup>
import { useId } from 'vue'
const id = useId();
</script>
<template>
<label :for="id">label</label>
<input :id="id" />
</template>
Component
deferred Teleport
Teleportにdefer
プロパティが追加されました。defer
がついたTeleportは他の同じ更新サイクル内の全DOMコンテンツがレンダリングされるまで待機した後にmountを行います。
以下のサンプルコードはEvan氏のPRに記載があった例を少しいじったものです。defer
プロパティがない場合には#target
のDOMはレンダリングされていないため失敗しますが、defer
によりtargetのDOMがレンダリングされた後にmountされるため正常に動作します。
<template>
<Teleport defer to="#target">teleport!</Teleport>
<div id="target"></div>
</template>
Evan氏は当該のPR中でSuspense内での利用についても言及しています。以前はSuspense内でTeleportを利用すると外部の既にレンダリングされたDOMしか対象に出来ませんでしたが、下記の様な使い方も可能になります。
<Suspense>
<div>
<AsyncComp />
<Teleport defer to="#target">...</Teleport>
<div id="target"></div>
</div>
</Suspense>
その他Vue全体
reactive props destructureがデフォルトになる
以前より実験的機能となっていましたが、以下の様なdefinePropsの定義した場合でもリアクティブ性を維持することが可能となりました。
import { watchEffect } from 'vue';
const { msg } = defineProps(['msg']);
watchEffect(() => {
console.log(msg);
});
利用したくない場合はviteの場合以下のオプションで変更可能です。(以前はscript.propsDestructure
でした)
export default defineConfig({
plugins: [
vue({
features: {
propsDestructure: false
}
})],
})
watchやwatchEffectなどでpause/resumeが可能となる
下記の様にpause
やresume
で処理を一時停止、再開させることが出来ます。
<script setup>
import { ref, watch } from 'vue'
const input = ref('')
const { pause, resume } = watch(input, (val) => {
console.log(val)
})
</script>
<template>
<input v-model="input" />
<button @click="pause()">pause!</button>
<button @click="resume()">resume!</button>
</template>
その他の機能改善
- 配列の追跡を最適化してパフォーマンス・メモリ使用量改善
- custom-elementのヘルパー関数をはじめとした様々な改善
- TypeScriptの型改善
- SSR/hydration関連の改善
-
watch
のdeep
を数値で調整可能 -
app.onUnmount
などいくつかの関数追加 - などなど(まだまだ様々な改善があります!)・・・
所感
軽い気持ちでVue 3.5の新機能を体験しようと思いましたが、書ききれないくらいのボリュームで安定版のリリースが楽しみです。Evan氏をはじめ、全てのVueコントリビューターに感謝をしつつ終わりとさせていただきます。
Discussion