以下のように v-for
の中で ref
を使う場合、this.$refs[n]
でオブジェクトを取得することができます。
// HogeHogeというコンポーネントを使っていますが、
// nameというメソッドを呼ぶとvalueパラメータで与えられた
// オブジェクトのnameを返すものとします。
<template>
<ul>
<li v-for="(item, i) in items" :key="i">
<hoge-hoge ref="hoge" :value="item" />
<button @click="test(i)">{{ item.name}}</button>
</li>
</ul>
</template>
<script>
data() {
return {
items: [
{ name: 'AAA' },
{ name: 'BBB' },
{ name: 'CCC' }
]
}
}.
methods: {
test(i) {
console.log(this.$refs.hoge[i].name)
}
}
</script>
このコードを実行すると、3つのボタンが表示されます。
AAAというボタンをクリックするとAAAがコンソールログ出力され、BBBというボタンをクリックするとBBBが出力されます。
ここで、プログラムの中で items
配列の要素の順番を入れ替えてみます。
this.item = [
{ name: 'BBB' },
{ name: 'AAA' },
{ name: 'CCC' }
]
ボタンのラベルはこの配列の順番に表示されますが、ボタンをクリックすると、困ったことに異なるnameが出力されることがあります。
refはリアクティブではないため、オブジェクトを再利用する際に、$refsの配列の順番まで面倒を見てくれないのかも知れません。
仕方ないので、こんな感じでこの問題を回避してみました。
<template>
<ul>
<li v-for="(item, i) in items" :key="i">
<hoge-hoge ref="hoge" :value="item" :hoge-key="i" /> // hoge-keyを追加
<button @click="test(i)">{{ item.name}}</button>
</li>
</ul>
</template>
<script>
import _ from 'lodash'
data() {
return {
items: [
{ name: 'AAA' },
{ name: 'BBB' },
{ name: 'CCC' }
]
}
}.
methods: {
test(i) {
const hoge = _.find(this.$refs.hoge, (ref) => {
return Number(_.get(ref, '$attrs.hoge-key', -1)) === i
})
if (hoge) {
console.log(hoge.name)
}
}
}
</script>
HogeHogeオブジェクトに、hoge-key
というプロパティを追加して、インデックスの i
を代入しておきます。
クリックイベントで、インデックス i
を受け取り、this.$refs.hoge
配列の中から、hoge-key
プロパティと i
が一致するオブジェクトを探します。
hoge-key
プロパティの値は、$attrs.hoge-key
で取得できましたが、果たして$attrs
は公式に使って良いプロパティなのか分からなかったので少々不安ではありますが、一応はこれで動いております。