カスタムディレクティブ
Vue.jsにおけるディレクティブはデータの変更に応じたDOMの処理をテンプレート内で記述可能な形で提供する仕組みです。v-ifやv-repeatなど、Vue.jsにおけるディレクティブの基本については前回の記事で解説しました。今回は自分でカスタマイズしたディレクティブを定義するための仕組みであるカスタムディレクティブについて紹介します。
カスタムディレクティブを登録するには、Vue.directive(id, definition)を使用します。第2引数で渡すdefinitionのオブジェクトは、以下に示すbind, update, unbindという3つのフック関数や、いくつかのオプションを記述することができます。
| 項目 | 説明 |
|---|---|
| bind | 初めてエレメントに紐付けられた時のみに呼ばれるフック関数。例えば、イベントリスナーの追加など一度だけの処理を行う。 |
| update | バインドされているvalueが変更されるたびに呼ばれるフック関数(前の値と新しい値が引数で渡される)。初回はbindの直後に呼ばれる。ディレクティブ定義時のdefinitionにfunctionを渡した場合はupdateとして扱われる。 |
| unbind | ディレクティブがエレメントから取り外されるタイミングで一度呼ばれるフック関数。例えば、イベントリスナーの削除などの処理を行う。 |
| isLiteral |
属性の値(expression)として単一文字列を受け取りたい場合にtrueをセット。 例: <div v-literal-dir="foo"></div> |
| twoWay | VMインスタンスから受け取った値をディレクティブ内で双方向で書き換えたい場合にtrueをセット。 |
| acceptStatement |
v-onディレクティブのように属性の値にインラインの式を記述したい場合にtrueをセット。 例: <div v-my-directive="a++"></div> |
| deep |
入れ子のオブジェクトのプロパティ値が変更された際にupdateフック関数を呼びたい場合にtrueをセット。 例: <div v-my-directive="obj"></div> |
また、カスタムディレクティブで定義したフック関数内の処理でthisがアクセスできるプロパティがいくつか用意されています。
| 項目 | 説明 |
|---|---|
| el | ディレクティブに紐付いているエレメント。 |
| vm | ディレクティブを呼び出しているコンテキストに対応しているVMインスタンス。 |
| expression | ディレクティブを呼び出す際の引数への値として与えられる表記。引数自身やフィルターは含まない。 |
| arg | ディレクティブを呼び出す際の引数自身。 |
| raw | ディレクティブを呼び出す際の引数と値のそのままの文字列。 |
| name | prefix(“v-”など)を排除したディレクティブ名。 |
以下にそれぞれのフック関数やthisのプロパティを使用した簡単なカスタムディレクティブの例を示します。
<div id="app">
<input v-model="msg">
<div v-my-directive="LightSlateGray : msg"></div>
</div>
<script>
Vue.directive('my-directive', {
isLiteral: false,
twoWay: false,
acceptStatement: false,
deep: false,
bind: function () {
this.el.style.color = '#fff';
this.el.style.backgroundColor = this.arg;
},
update: function (newValue, oldValue) {
this.el.innerHTML =
'name - ' + this.name + '<br>' +
'raw - ' + this.raw + '<br>' +
'expression - ' + this.expression + '<br>' +
'argument - ' + this.arg + '<br>' +
'value - ' + newValue;
},
unbind: function () {
this.el.innerHTML = '';
}
});
var vm = new Vue({
el: '#app',
data: {
userInput: '',
msg: 'メッセージ'
}
});
// 3秒後にVMインスタンスを破棄する
setTimeout(function(){
vm.$destroy();
}, 3000);
</script>
「v-」というprefixをディレクティブ使用時に付けて実行すると、対象のエレメントの下にDOMが生成され、3秒後の$destroyによりunbindが呼ばれて消えます。
渡された値を変換するためのカスタムフィルターと比較すると、カスタムディレクティブは渡された値に応じてDOMの変更も管理できる点が異なります。
デフォルトではカスタムディレクティブなどを使用するときにv-というprefixがつきます。このprefixを変更したい場合はVue.config.prefixに新規の値をセットします。
Vue.config.prefix = "data-";
例えば上記のように変更すると<div data-my-directive=”foo”></div>と記述することができます。

