0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Vue.js] 子コンポーネント内の DOM の参照を取得する

Posted at

はじめに

たとえば以下のようなコンポーネントがあったとします。

InputComponent.vue
<template>
  <input type="text" class="form-control">
</template>

今回はこのコンポーネントを利用する親コンポーネントから、コンポーネント内部の input タグへの参照を取得することを目指します。
親からフォーカスを当てたい時などに使えると思います。
Vue のバージョンは3系を前提とし、 Composition API を利用します。

親コンポーネント

まず親からどうやって使うかを考えてみます。
単純に子コンポーネントを ref で参照すると、残念ながらDOMではなくコンポーネントインスタンスへの参照になってしまいます。

ParentComponent.vue
<template>
  <input-component ref="inputRef" />
</template>

<script lang="ts">
import { defineComponent, ref, onMounted } from 'vue'
import InputComponent from './components/InputComponent.vue'

export default defineComponent({
  components: {
    InputComponent,
  },
  setup() {
    const inputRef = ref<HTMLInputElement | undefined>()
    onMounted(() => {
      // HTMLInputElement ではなくコンポーネントインスタンスが取得される
      // 当然 focus メソッドなど存在しない
      console.log(inputRef.value)
    })
    return {
      inputRef
    }
  }
})
</script>

では子コンポーネントからどうやってデータ(DOM)を上げるかというと、 v-model (= emit )を利用します。
2系の場合は sync 修飾子 です。

ParentComponent.vue
<template>
  <input-component v-model:inputRef="inputRef" />
</template>

これで子コンポーネントからDOMを取得する準備ができました。

子コンポーネント

子コンポーネントでは、 ref で取得したDOMの参照を emit を通して上げるだけです。

InputComponent.vue
<template>
  <input type="text" class="form-control" ref="ref">
</template>

<script lang="ts">
import { defineComponent, computed } from 'vue'

export default defineComponent({
  props: {
    inputRef: {
      type: HTMLInputElement,
    },
  },
  setup(props, { emit }) {
    const ref = computed<HTMLInputElement | undefined>({
      get() {
        return props.inputRef
      },
      set(value) {
        emit('update:inputRef', value)
      }
    })

    return {
      ref
    }
  }
})
</script>

refWritableComputed を渡すのがポイントです。 setemit() します。

おわりに

親から子コンポーネント内部のDOMの参照を取得できるようになりました。
id を渡して getElementById を呼んだり、または子コンポーネントに focus メソッドを用意してコンポーネントインスタンスを直接参照する方法などもありますが、個人的にはこちらのほうがすっきりしてていいと思います。
Atomic Design などで設計する時の参考になれば。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?