124
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

Organization

[Vue.js] $refsでコンポーネント内の子要素を触る

ちょっと詰まったところがあったのでメモがわりに。

$refsから子要素を触ろう

配置したコンポーネントを動的に取得して、スタイルとかプロパティを取得して弄りたかったり、処理を実行させたかったりする時がある。
そういう時は触りたい要素にrefを設定すると$refsから取得できるようになる。

<template>
  <hogehoge ref="hogehoge" />
</template>

<script>
  ...
    let component = this.$refs.hogehoge /// コンポーネントインスタンス hogehoge
  ...
</script>

リストレンダリングした物も$refsで取れる

v-forでリストレンダリングしたコンポーネントも$refsで取得することができる。

<template>
  <hogehoge v-for="item in hoge" ref="hogehoge" />
</template>

<script>
  ...
    let component = this.$refs.hogehoge[0] /// リストレンダリングした hogehoge の先頭要素
  ...
</script>

この例のように、リストレンダリングしたオブジェクトに$refsからアクセスすると
それぞれのインスタンスが順番に格納された配列が返ってくる。

ひらめいた

これ、同じref名を設定してやれば配列で格納されるって事じゃないの?
じゃあリストレンダリングの後に同じref名でコンポーネント設置してやれば
配列の最後に必ず特定の状態のコンポーネント入れられるんじゃね?

<template>
  <hogehoge v-for="item in hoge" ref="hogehoge" />
  <fugafuga ref="hogehoge" />
</template>

されない

そんな訳がなかった。
同名refが配列として格納されるのではなく、あくまでリストレンダリングしたコンポーネントを配列として返しているだけ
じゃあ上に書いたコードだとどのような結果になるかというと

<script>
  ...
    let component = this.$refs.hogehoge /// コンポーネントインスタンス fugafuga
  ...
</script>

<fugafuga>要素だけが取れる。
つまり同名のrefを持つコンポーネントを2つ以上設置した場合、後に配置した方に上書きされるのだった。
これに気付かず型チェックやら何やらの判定をコンソールに吐き出して散々デバッグする苦い目にあったのでメモ替わりに投稿。

他に気をつける事

コンポーネントインスタンスにアクセスする関係上、親コンポーネントがレンダリングされていない状態で既に処理を行っている
createdbeforeMountでは当然使えない。computedも最初の処理時にDOM要素が無いのでif条件で何とかしないと使えない。

あとAxiosとかの非同期処理で引っ張ってきたデータを元にリストレンダリングしている場合、
当然非同期処理の終了を待たないと$refsの中を見ても何も無いので注意。

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
124
Help us understand the problem. What are the problem?