Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

今日、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

studist
「伝えることを、もっと簡単に」をミッションにビジュアルSOPマネジメントプラットフォームのBtoB SaaS「Teachme Biz」を開発・運営するスタートアップ
https://medium.com/studist-dev
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
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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
ユーザーは見つかりませんでした