基礎からメモ: Vue.js CH2-p85 DOMの直接参照

DOMに直接アクセスするには、インスタンス・プロパティの$el$refsを使う。これらは、ライフサイクルで言うとmounted(インスタンスのマウント後)以降でなければ使えない。

$el

$elは、コンポーネントのテンプレートを囲っているルート要素を指す。

var app = new Vue({
  el: '#app',
  mounted: function() {
    console.log(this.$el);
  }
});

コンソールに<div id="app">........</div>という形でルート要素が表示されているはずだ。

$refs

ルート以外の要素は、ref$refsでアクセスする。refはアクセスされるテンプレート側につける特殊な属性。

[index16.html]

<div id="app">
    <p ref="hello">Hello</p>
..........
</div>

このようにref属性で何らかの名前を付けておき、次のようにアクセスする。

[main02.js]

var app = new Vue({
  el: '#app',
  mounted: function() {
    console.log(this.$refs.hello);  // <- ref属性の付いたp要素のDOMを指す。
  },
});

コンソールにp要素のDOMが表示される。

<p>Hello</p>

$el や $refs は仮想DOMの変更で上書きされる

$el$refs は、仮想DOMではない。操作するたびに描画するので、仮想DOMがデータの変更に応じて描画すると上書きされてしまうことがある。そのため、$el$refs は一時的な変更でのみ使うべき。

例えば次のようにDOMから数値を取得し、ボタンをクリックするたびにその数値を+1するメソッドを紐付ける。そのうえでv-ifで表示・非表示を切り替えるボタンを設置する。

<button v-on:click="handleClick">カウントアップ</button>
    
<p ref="count" v-if="show">0</p>
<button v-on:click="show=!show">v-if 表示/非表示</button>

カウントアップというボタンを押すと数値が1ずつアップするが、一度v-ifを使ったボタンで非表示にし表示に戻すと数値が 0 に戻っているはずだ。

これに対して次のようなv-showを使った表示・非表示を切り替えるボタンを設置すると、スタイルで非表示にしているだけなので、数値はブラウザで再読み込みしないかぎり維持される。v-showv-ifと違い仮想DOMを変更しないからだ。

<p ref="count2" v-show="ok">0</p>
<button v-on:click="ok=!ok">v-show 表示/非表示</button>

Vue側は次のようになっている。

var app = new Vue({
  el: '#app',
  data: {
    show: true,
    ok: true
  },
  methods: {
    handleClick() {
      var count = this.$refs.count;
      var count2 = this.$refs.count2;
      if (count) {
        count.innerText = parseInt(count.innerText, 10) + 1;
      }
      if (count2) {
        count2.innerText = parseInt(count2.innerText, 10) + 1;
      }
    }
  }
});
  • DOMに直接アクセスするには、インスタンス・プロパティの$el$refsを使う。
  • $el$refs での変更は仮想DOMの変更で上書きされるので、一時的なDOMの操作に使う。