はじめに
Vue2では$refs
を利用して子コンポーネントにアクセスして、気軽にデータを取得したり関数を実行していました。
最近Vue3に移行したのですが、$refs
と同様の記載方法を把握するのに時間がかかったので、同じように困っている人の手助けになるような記事を残します。
環境
- Vue3
- TypeScript
- Composition API
-
<script setup>
構文
子コンポーネント
まずは子コンポーネント内の実装を行います。
<script setup lang="ts">
import { ref } from 'vue';
const count = ref<number>(0);
const countUp = () => {
count.value++;
}
const callDoubleCount = ():number => {
return count.value * 2;
}
defineExpose({
count,
countUp,
callDoubleCount,
});
</script>
上記のように記載します。重要なのはdefineExpose
の部分です。
defineExpose
コンパイラマクロ
<script setup>
構文ではデフォルトで内部のアクセスを閉じているので、defineExpose
コンパイラマクロというものを利用して、意図的にプロパティを公開する必要があります。
上記のようにdefineExpose
内で宣言した内容は別のコンポーネントから参照出来るようになりました。
親コンポーネント
子コンポーネントにアクセスしてデータを参照したり関数を実行するには以下のように実装します。
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import Child from './Child.vue';
const child = ref<InstanceType<typeof Child> | null>(null);
onMounted(() => {
console.log(child.value?.count); // 0
child.value?.countUp();
console.log(child.value?.callDoubleCount()); // 2
})
</script>
<template>
<div>
<Child ref="child"></Child>
</div>
</template>
ポイントを解説します。
template内でref属性の付与
まず、template内で呼び出している子コンポーネントに対しref属性を付与します。これはVue2の時と同様です。
<Child ref="child"></Child>
ref属性を付与したコンポーネントへのアクセス
ref属性にchildという命名を付与した場合、以下のように記述することでref属性を付与したコンポーネントにアクセス出来ます。
const child = ref(null);
この時重要なのは変数名です。変数名はtemplateに付与したref属性と同じ名前にする必要があります。
例えば以下のようにref属性と別の名前で変数を定義しても、何も取得出来ません。
const child2 = ref(null);
onMounted(() => {
console.log(child2.value); // undefined
})
コンポーネントを格納した変数の型定義
これが一番情報が少なかったのですが、ref属性を取得して格納した変数の型定義についてです。
const child = ref<InstanceType<typeof Child> | null>(null);
まずmountされてDOM要素が生成されるまではアクセス出来ないのでnull型を定義します。
そしてunion型にして、InstanceType<typeof コンポーネント名>
で型定義することで、コンポーネントの型定義を読み込むことが可能です。
こちらに関しては公式ドキュメントに記載がありました。
Vue.js公式ドキュメント | テンプレート参照を型定義する
onMounted実行後に子コンポーネントにアクセスする
先ほども触れましたが、まずmountされてDOM要素が生成されるまではアクセス出来ません。仮にアクセスを試みた場合、以下のようにnullを返されます。
const refSample = ref<InstanceType<typeof RefSample> | null>(null);
console.log(refSample.value); // null
.value
プロパティにアクセスする
onMounted実行後にDOM要素が生成されてコンポーネント内の情報にアクセス出来るようになりました。情報を取得するには、.value
プロパティにアクセスする必要があります。
また、mounted前は.value
にアクセスしてもnullなので、.value
に値が存在する場合の処理として、オプショナルチェーンを利用した書き方をします。
console.log(child.value?.count); // 0
child.value?.countUp();
console.log(child.value?.callDoubleCount()); // 2
おわりに
以上でVue3×TypeScript×Composition APIで、子コンポーネントにrefを利用してアクセスする方法となります。
ネットで検索しても情報が散らばっているので、こちらの記事を見ることで困っている方が問題解決することを願っています。
Twitterもやってます