Edited at

Vueで直接DOMノードを参照するプロパティを知ってアハ体験したのでまとめてみた

今日、Vueのコードを書いていて、ふと vm.$el の存在を思い出して猛烈に感動しました。

なので、Vueインスタンスから特定のDOM要素を参照できる方法を一覧してみようと思います。

ちなみに、途中までプロパティセレクタを使ったquerySelectorで、リストの特定要素を指定して意図通りに動いたものの……という顔をしてました

基本的に公式ドキュメントの API — Vue.js に書いてあることの引用です。


知ってマジ神だなって奴


vm.$el - コンポーネントのルートDOMを得る

https://jp.vuejs.org/v2/api/index.html#vm-el


型: Element

Vue インスタンスが管理している ルートな DOM 要素です。



hoge.vue

<template>

<div class="hoge">
<p v-on:click="click">hoge</p>
</div>
</template>

<script>
default export{
methods:{
click(){
// <div class="hoge"> DOM が入る
console.log(this.$el)
}
}
}
</script>



vm.$refs - 子DOM/子コンポーネントを得る

https://jp.vuejs.org/v2/api/index.html#vm-refs


型: Object

ref 属性によって登録されたDOM 要素のオブジェクトとコンポーネントインスタンスです。


公式ドキュメントの 特別な属性 - ref と併せてお読みください。

<!-- vm.$refs.p は DOM ノード -->

<p ref="p">hello</p>

<!-- vm.$refs.child は child-component のインスタンス -->
<child-component ref="child"></child-component>

とのことなので、どこにrefをつけるかで返り値が変わるようです。

ドキュメントにもありますが、レンダリング後にvm.$refの値が入るようなので、この値が存在しなくてもエラーにならないようにハンドリングしてあげる必要があります。


一応できるやつ


vm.$parent - 親コンポーネントを得る

https://jp.vuejs.org/v2/api/index.html#vm-parent


型: Vue instance

現在のインスタンスが1つ持つ場合は、親のインスタンスです。


親コンポーネントのインスタンスが返ります。 先程のvm.$elと組み合わせれば、親インスタンスのDOMノードが取得できますね。

まぁ、親のコンポーネントを操作するのはよほど密結合なコンポーネント同士でないと御法度でしょう。


<script>
default export{
methods:{
click(){
this.$parent.$el // 親コンポーネントのルートなDOM要素
}
}
}
</script>


slotを使うなら使いそうなやつ


vm.$scopedSlots

https://jp.vuejs.org/v2/api/index.html#vm-scopedSlots


型: { [name: string]: props => Array | undefined }

プログラム的にスロットにより配信されたコンテンツにアクセスするために使用されます。各名前付きスロット は自身に対応するプロパティを持ちます (例: slot="foo" のコンテンツは vm.\$slots.foo で見つかります)。default プロパティは名前付きスロットに含まれない任意のノードを含みます。


とりあえず現状自分がSlotを使わなさそうなので詳細については調べてません。


今回の要件ではあまりマッチしなさそうなもの


vm.$root

https://jp.vuejs.org/v2/api/index.html#vm-root


型: Vue instance

現在のコンポーネントツリーのルート Vue インスタンスです。現在のインスタンスが親を持たない場合、この値はそれ自身でしょう。


概ねvm.$parentと似たような使用感覚だと思うのですが、コンポーネントツリーのルートを取得しても Element 取得の用途ではあまり役に立たなさそうです。


vm.$children

https://jp.vuejs.org/v2/api/index.html#vm-children


型: Array

現在のインスタンスの直接的な子コンポーネントです。

\$children に対して順序の保証がなく、リアクティブでないことに注意してください。あなた自身、データバインディングに対して \$children を使用するためにそれを見つけようとする場合、子コンポーネントを生成するために配列と v-for を使用することを検討し、正しいソースとして配列を使用してください。


順序の保証がないというのは恐ろしいのでElementの取得用途では使いづらそうです。


まとめ

リストレンダリングされたコンポーネントの自分自身のエレメントを取得するときに良かったです。

また、動的にstyle計算するのに現在のDOMから値を取得したものを算出プロパティの計算に使うと、

現在のDOMの状態をリアルタイムに反映した値を作ることができると思います。

生DOMの値はリアクティブに参照できなかったデス。

値の参照用途として、VueインスタンスからDOM要素を直接参照する方法を知っておくのはかなり役立つのではないでしょうか。


余談


親のDOMがほしい

単に親DOMがほしいときは Element.parentNode で取れます

https://developer.mozilla.org/ja/docs/Web/API/Node/parentNode


子や孫のDOMが欲しい

DOM要素に対してもquerySelector が使えるので、先に絞り込んでその中から取得することもできます。

https://developer.mozilla.org/ja/docs/Web/API/Element/querySelector