Vue.js

Vue.js カスタムディレクティブとは

こんにちは!ともです(@_tomo_engineer)!

今回はVue.jsのカスタムディレクティブについて見ていきます。

参考にしたものは以下です。

基礎から学ぶVue.js(書籍)

Vue.js:日本語ドキュメント

カスタムディレクティブとは

カスタムディレクティブとはVue.jsのディレクティブを自作するための機能です。ドキュメントには以下の様に書かれていました。

カスタムディレクティブはデータの変更に伴い DOM がどのように変更されるかを定義することができる仕組みです。

v-modelなどのディレクティブではデータバインディングする事ができましたが、他のDOMを操作等はしませんでした。DOMを操作するための仕組みがカスタムディレクティブには存在するという事が分かります。

カスタムディレクティブの登録方法

グローバル・ローカル、どちらにも登録する事ができます。ローカルへの登録方法は次です。

new Vue({
  el: '#app',
  directives: {
      example: {
      }
   }
)}

上記の方法で、ディレクティブオプションにexampleという名前のカスタムディレクティブを定義しました。

カスタムディレクティブを利用する

次の様にカスタムディレクティブは利用します。

<div v-example></div>

この様にv-という接頭語をつけて、自作ディレクティブの名前を設定します。

DOMを操作する

new Vue({
   el: '#app',
   directives: {
      example: {
   bind: function(el) {
              el.style.backgroundColor = "red"
              el.style.width = "100px"
              el.style.height="100px"
         }
      }
   }
)}

この様な形で書きました。

bindされたとき、つまりexampleというカスタムディレクティブをバインドしたときに1度だけこのメソッドは起動します。

引数としてはelはexampleディレクティブをつけた要素を表しています。elを介してDOMの操作を行い、上の例ではstyleを設定しました。100px四方で赤色の四角形が表示されます。

この様にカスタムディレクティブではその他のディレクティブでは行えなかったDOMの操作を行える事が分かります。

またJavaScriptのプロパティやメソッドに簡潔にアクセスする事ができました。

使用可能なフック

bind以外のフックも存在します。

メソッド名 タイミング
bind ディレクティブが初めて要素と紐ついたとき
inserted 紐ついた要素が親Nodeに挿入されたとき
update 紐ついた要素を包含しているコンポーネントのVNodeが更新されたとき
componentUpdated 梱包しているコンポーネントと子コンポーネントのVNodeが更新されたとき
unbind 紐ついた要素からディレクティブが削除されるとき

次の様な物を書いてみました。

<div id="app">
        <input type="text"  v-example>
</div>
directives: {
        example: {
            bind: function(el) {
               console.log("bind")
            },
            inserted: function(el){
                console.log("inserted")
            },
            update: function(el){
                console.log("update")
            },
            componentUpdated: function(el){
                console.log("component")
            },
            unbind: function(){
                console.log("unbind")
            }
        }
    }

この状態でinputを操作したとしてもupdatecomponentUpdatedのフックは動作せずbindinsertedが動作します。

<div id="app">
        <input type="text" v-model="val" v-example>
</div>

v-modelを追加し、テキストを入力するとデータが変更した事を検知しupdatecomponentUpdatedが起動します。データを監視しながらDOMを操作する事ができます

フックの引数

el以外にも引数を持たせる事ができます。

引数 内容
el ディレクティブが付与されている要素
binding バインドされた値、引数、修飾子のオブジェクト
vnode 要素に対応するVNode
oldVnode 更新前のVNode

bindingはバインドされたものに関する情報がいくつか入っています。日本語ドキュメント:カスタムディレクティブ

bindingのもつプロパティの1つにoldValueとvalueがあります。あるinputの値が変化したときの変更前の値と変更後の値がそれぞれに格納されます。

<input type="text" v-model="val" v-example="val">

カスタムディレクティブに引数としてdata名を渡しました。これによりbindingのoldValueとvalueプロパティには変更前後のvalの値が格納されます。

updateを次の様にコンソールへ出力させてみました。

update: function(el, binding){
                console.log("update");
                console.log("前回"+binding.oldValue);
                console.log("今回"+binding.value);
 },

するとvalueの値を変更するたびに次の変更前後の値が表示されます。

変更前後の値がbindigのプロパティに格納されている事が分かります。

まとめ

カスタムディテクティブをみていき、次の事が分かりました。

まとめ
  • カスタムディレクティブによって、データを監視しながらDOMを操作する事ができる
  • フックにはbind・inserted・update・componentUpdated・unbindがある
  • フックの引数には要素に関する情報が格納されており、elを操作する事でDOMを操作できる
  • JavaScriptのメソッドに簡潔にアクセスする事ができる

まだ実戦でどの様な場合にカスタムディレクティブを利用するのかイメージができていませんが、DOMの操作を行う場合はカスタムディレクティブの利用を検討してみようと思います。