【Vue 3】Composition APIでテンプレート参照する方法

Vue.jsのテンプレート参照は非常に便利であり、Options APIではthis.$refs.xxxという形式で参照が行えた。しかし、Composition APIではOptions API形式の記述法ではテンプレート参照ができなくなったため、Composition APIに則した形で記述を行う必要がある。

テンプレート参照とは?

Vue インスタンスからテンプレート内の DOM 要素や子コンポーネントのインスタンスに直接アクセスするための機能を提供する。

DOM 要素に直接アクセスできるとはどういうことか?

以下のようなinput要素があると仮定し、input DOM要素を取得し、その要素が持つイベント処理などを発火させることができるというもの。

<input ref="input">

仮にinput要素のfocusイベントを発火させたい場合、Vue.jsのOptions APIでは以下のように記述する。

<template>
  <div>
    <input ref="input">
  </div>
</template>

<script>
export default {
  mounted () {
    this.$refs.input.focus()
  }
}
</script>

上記の記述により、初期描画のタイミングでinput要素のfocusイベントが発火するようになる。だが、これはあくまで単一のDOM要素に対する参照である。

Vue.jsでは基本的に複数のコンポーネントをモジュールとして定義し、import exportすることでアプリケーションの構築を行う。つまり、コンポーネントはそれぞれ独立したインスタンスを持つ。詳しくは公式ドキュメントを参照:コンポーネントの基礎

コンポーネントを連結させてアプリの開発を行う過程で、特定の条件やタイミングで子コンポーネントのメソッドを発火させたいケースなどにテンプレート参照は有効な手段となる。

Composition APIでテンプレート参照する記述方法

それでは、Composition APIのテンプレート参照を使って子コンポーネントのメソッドを発火させる方法について解説する。

親コンポーネント側と子コンポーネント側でそれぞれ必要な定義がある。(サンプルコードを参照)

親コンポーネント側の記述

以下のコードは、チャットアプリのトークルーム一覧画面を実装する想定である。親コンポーネント(Chat.vue)で子コンポーネント(ChatList.vue)のメソッドを発火させたい。

ポイントとなるのは以下の3点

  • テンプレート側で参照を定義(ref=”roomlistRef”)
  • スクリプト側で要素の参照を保持する ref を宣言(const roomlistRef = ref(null))※定数名は、テンプレートの ref の値に一致させる必要がある。
  • setup()でroomlistRefをreturnする
<template>
  <Header />
  <v-main class="d-flex">
    <ChatList      
      :changeMode="changeMode"
      ref="roomlistRef"
    />
  </v-main>
</template>

<script>
import { ref, onMounted } from 'vue'
import ChatList from './ChatList.vue'

export default {
 component: { ChatList },
 setup () {
  const roomlistRef = ref(null)
  onMounted(() => {
    roomlistRef.value.init()
  })
  
  return {
    roomlistRef
  }
 }
}
</script>

上記の定義を行うことで、子コンポーネントのテンプレート参照を行えるようになる。

※ <script setup>を使用する場合は、returnする必要はない

<script setup>
// ロジック
</script>

子コンポーネント側の記述

子コンポーネント側では、発火させたい関数を定義し、setup内でreturnしてあげればOK。

export default {
 setup () {
  const init = () => {
    console.log('hogehoge')
  }
  return {
    init
  }
 }
}

関連記事

コメント

この記事へのコメントはありません。