Vue.js(v2, v3)のrefsの使い方(親から子の要素参照)

Vue.js Vue.js

Vue.jsでrefsを使用して、コンポーネントの要素を参照する方法について書いています。
Vue.jsのバージョンは2と3(Composition API)で動作を確認しています。

公式のドキュメントはこちらに記載してあります。
Vue.js
Vue.js - The Progressive JavaScript Framework

Vue.jsのrefsとは?

refsを使うことで、親コンポーネントから子コンポーネントを参照することができます。
テキストエリアやテキストボックスの内容を親コンポーネントから参照して取得したり、変更したりすることが可能です。

Vue.js(v2)のrefs使用例

バージョン2の時は、下記のように$refsを使うことで子コンポーネントを参照できました。

子コンポーネントがこんな感じの場合には

<template>
    <div>
        <input type="test" v-model="text" />
        <textarea v-model="textArea"></textarea>
    </div>
</template>
<script>
export default({
    data : function (){
        return {
            text: '',
            textArea: '',
        }
    }
})
</script>

親コンポーネントからこんな感じで使うことができます。

<template>
  <div id="app">
    <text-and-text-area ref="texts" />
    <button @click="testAction">test</button>
  </div>
</template>

<script>
import TextAndTextArea from './components/TextAndTextArea.vue'

export default {
  name: 'App',
  components: {
    TextAndTextArea
  },
  mounted: function (){
    console.log(this.$refs.texts);
  },
  methods: {
    testAction: function () {
      console.log(this.$refs.texts.text); // テキストボックスの入力値が参照できる
      console.log(this.$refs.texts.textArea); // テキストエリアの入力値が参照できる
    }
  }
}
</script>

解説

子コンポーネントをtext-and-text-areaというタグ名で使用しています。
これはテキストボックスとテキストエリアだけが表示されるコンポーネントです。

ref="texts"で子コンポーネントを参照できるようにref属性を付与しています。
画面ロード(mounted)時にthis.$refs.textsを呼び出して、ref属性を付与したコンポーネントの内容をコンソールに出力しています。

ボタンを押したとき(testAction実行時)には、子コンポーネントで定義されているdata(text, textArea)に$refsを使用してアクセスしています。
これで、コンソールにそれぞれ入力した内容が表示されます。

Vue.jsのバージョン3(Composition API)を使う場合は使い方が変わりました。
次項から実際の使い方を確認します。

Vue.js(Composition API)でrefsを使う

Composition APIでrefsを使う方法を確認します。

Vue.js(v3)のrefs使用例

上記で書いたv2のコンポーネントをv3のComposition APIで書いてみました。
子コンポーネントが下記のようになります。

<template>
    <div>
        <input type="test" v-model="text" />
        <textarea v-model="textArea"></textarea>
    </div>
</template>
<script>
import { ref } from 'vue'
export default({
  setup () {
    const text = ref('')
    const textArea = ref('')

    return {
      text,
      textArea
    }
  }

})
</script>

親コンポーネントは下記のようになりました。

<template>
  <div id="app">
    <text-and-text-area ref="texts" />
    <button @click="testAction">test</button>
  </div>
</template>

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

export default {
  components: {
    TextAndTextArea
  },
  setup () {
    const texts = ref(null)
    const testAction = () => {
      console.log(texts.value.text);
      console.log(texts.value.textArea);
    }

    onMounted(() => {
      console.log(texts.value);
    })

    return {
      texts,
      testAction
    }
  }
}
</script>

解説

Composition APIでv2から書き方が結構変わりました。

今回はrefの箇所に関してのみ解説します。
v2で使っていたthis.$refsを使わなくなりました。
refを使いたい場合は、v2の時と同じようにref属性をタグにつけます。

まず、setup関数の中でref(null)を代入した変数を作ります。

const texts = ref(null)

この時の変数名をrefに設定した値と同じにします。(ここではtexts)
変数名がrefの設定値と違うと、下記のようなエラーが出ます。

Uncaught (in promise) TypeError: Cannot read property 'texts' of null

変数を作った後はsetup関数の最後にreturnで返すようにしておきます。

return {
  texts, // 設定したrefにアクセスできる変数
  testAction
}

あとは使いたいところでtexts.valueにアクセスすると、refを設定したコンポーネントの値にアクセスできます。
texts.value.texttexts.value.textAreaといった感じです。

動作確認

画面ロード時にmountedが走ったときに、refにアクセスできていることが確認できました。

何か入力して、ボタンを押した場合には、refを使用してコンソールに入力内容が返ってきました!

refで孫にアクセスしたい場合は?

「親コンポーネント=>子コンポーネント=>孫コンポーネント」とコンポーネントの階層ができている場合です。

このときに親から孫のコンポーネントにアクセスしたいというときには
まず、子コンポーネントと孫コンポーネントでは同様にref(null)で変数を作って、返しておく必要があります。

後は親からchild.value.Grandchildのように、[子].value.[孫]の形でアクセスすることができます。

コメント

タイトルとURLをコピーしました