いきなり結論サンプル
See the Pen
$refsで特定のinputタグにフォーカス by riotam (@riotam4)
on CodePen.
はじめに
今回、Vue.jsで任意のタグにフォーカスする機能を実装していた際、職場の上司から教えてもらったことがあったので、まとめつつ共有します。
まずは、良くないと指摘されたコードから…
getElementByIdを使った、あまりよくない例
See the Pen
$refsで特定のinputタグにフォーカス(5) by riotam (@riotam4)
on CodePen.
解説
単純な仕組みです。
ボタンを押すと、focusInput
メソッドが発火します。メソッドはこんな感じ。
focusInput() {
document.getElementById('focusThis').focus();
}
getElementById
が、そのあとの引数に入っているidを持つ要素を読み込んでいます。
なぜVue.jsでこの方法が良くないか
いくつものコンポーネントで構成されることの多いVue.jsでは、安易にidを指定すること自体が高リスクとのこと。
Vue.jsでは、1つのページがたくさんのファイル(コンポーネント)でできていることも多いので、どうしても見通しが悪くなりがち。
確かに、idがぐちゃぐちゃに書かれてしまったら、狙っていたタグでの挙動が得られなかったときに、原因の究明が大変になりそう。
$refsを使って任意のタグを読み込む
See the Pen
$refsで特定のinputタグにフォーカス by riotam (@riotam4)
on CodePen.
そこで、$refs
での書き方に変更しました。
focusInput() {
this.$refs.focusThis.focus();
},
<input ref="focusThis">
メソッドの中身と、タグ内を書き換えただけです。
thisは「new Vueしたオブジェクト」を指します。
$refs
とその後ろのfocusThis
組み合わせは、HTML側でref=focusThis
を指定しているタグを読み込みます。
ちなみに、ワンライナーで書いたら、こんな感じになります。
See the Pen
$refsで特定のinputタグにフォーカス(2) by riotam (@riotam4)
on CodePen.
$refsで指定したrefが複数あった場合の挙動
getElementById
の場合は、同じidのタグが複数あった場合、1番目のタグが読み込まれます。
Vue.jsでは、この挙動が問題になると考えられるのですが、$refsは少し違った挙動をします。
今回、inputタグ3つに同じrefをつけて出力してみました。
すると…
TypeError: this.$refs.focusThis.focus is not a function
この様なエラーで返されます。
そんな関数ないとのこと…。
this.$refs.focusThisの中身
console.logでthis.$refs.focusThis
を出力してみると…
See the Pen
$refsで特定のinputタグにフォーカス(3) by riotam (@riotam4)
on CodePen.
(3) [input, input, input]
0: input
1: input
2: input
なんと、同じrefが書かれたタグ達が配列になって格納されている…!!
これで、たくさんのコンポーネントでぐちゃぐちゃになってしまっているVueファイルであっても、安心。
なんせ、全部拾ってくれるので。
キーを指定する
配列として格納されているので、キー指定してやると動作してくれます。1番目を取得したい場合は、
this.$refs.focusThis[0].focus()"
このようにすると良いです。動作を試してみてください。
See the Pen
$refsで特定のinputタグにフォーカス(4) by riotam (@riotam4)
on CodePen.
まとめ
- Vue.jsでは安易にidで指定するとカオスになる怖れがある
- 任意のタグを取得したいなら、idではなく
ref
でタグを指定して、$refs
を使うのがおすすめ ref
で指定したタグが複数あった場合、配列に格納される便利仕様- その際は、キーを忘れずに