ガイド
基本的な使い方
- インストール
- はじめに
- Vue インスタンス
- テンプレート構文
- 算出プロパティとウォッチャ
- クラスとスタイルのバインディング
- 条件付きレンダリング
- リストレンダリング
- イベントハンドリング
- フォーム入力バインディング
- コンポーネントの基本
コンポーネントの詳細
- コンポーネントの登録
- プロパティ
- カスタムイベント
- スロット
- 動的 & 非同期コンポーネント
- 特別な問題に対処する
トランジションとアニメーション
- Enter/Leave とトランジション一覧
- 状態のトランジション
再利用と構成
- ミックスイン
- カスタムディレクティブ
- 描画関数とJSX
- プラグイン
- フィルター
ツール
- 単一ファイルコンポーネント
- テスト
- TypeScript のサポート
- プロダクション環境への配信
スケールアップ
- ルーティング
- 状態管理
- サーバサイドレンダリング
- セキュリティ
内部
- リアクティブの探求
移行
- Vue 1.x からの移行
- Vue Router 0.7.x からの移行
- Vuex 0.6.x から 1.0 への移行
その他
- 他のフレームワークとの比較
- Vue.js コミュニティへ参加しましょう!
- チームに会おう
v2.x 以前のドキュメントです。 v3.x のドキュメントを見たい場合はこちら
カスタムディレクティブ
最終更新日: 2019年7月22日
基本
Vue.js 本体で出荷されたディレクティブの標準セットに加えて (v-model と v-show)、カスタムディレクティブ (custom directive) を登録することができます。Vue 2.0 では、コードの再利用と抽象化における基本の形はコンポーネントです。しかしながら、通常の要素で低レベル DOM にアクセスしなければならないケースがあるかもしれません。こういった場面では、カスタムディレクティブが役立つでしょう。ひとつの例として、以下のような input 要素へのフォーカスが挙げられます:
ページを読み込むと、この要素はフォーカスを手に入れます。実際、このページに訪れてから他のところをクリックしていなければ、この input にフォーカス(注意:モバイル Safari では自動でフォーカスしません)が当たっているでしょう。さあ、これを実現させるディレクティブを作りましょう。
// `v-focus` というグローバルカスタムディレクティブを登録します
Vue.directive('focus', {
// ひも付いている要素が DOM に挿入される時...
inserted: function (el) {
// 要素にフォーカスを当てる
el.focus()
}
})
代わりにローカルディレクティブに登録したいならば、コンポーネントの directives オプションで登録できます:
directives: {
focus: {
// ディレクティブ定義
inserted: function (el) {
el.focus()
}
}
}
これでテンプレートで、以下のような新しい v-focus 属性が使えるようになります。
<input v-focus>
フック関数
directive definition object はいくつかのフック関数(全て任意)を提供します:
bind: ディレクティブが初めて対象の要素にひも付いた時に 1 度だけ呼ばれます。ここで 1 回だけ実行するセットアップ処理を行えます。inserted: ひも付いている要素が親 Node に挿入された時に呼ばれます(これは、親 Node が存在している時にだけ保証します。必ずしも、ドキュメントにあるとは限りません)。update: ひも付いた要素を抱合しているコンポーネントの VNode が更新される度に呼ばれます。しかし、おそらく子コンポーネントが更新される前でしょう。 ディレクティブの値が変化してもしなくても、バインディングされている値と以前の値との比較によって不要な更新を回避することができます。(フック引数に関しては下記を参照してください)componentUpdated: 抱合しているコンポーネントの VNode と子コンポーネントの VNode が更新された後に呼ばれます。unbind: ディレクティブがひも付いている要素から取り除かれた時に 1 度だけ呼ばれます。
次のセクションで、これらのフックに渡す引数(すなわち el, binding, vnode, oldVnode)を見ていきましょう。
ディレクティブフック引数
ディレクティブフックには以下の引数が渡せます:
el: ディレクティブがひも付く要素。DOM を直接操作するために使用できます。binding: 以下のプロパティを含んでいるオブジェクト。name:v-接頭辞 (prefix) 無しのディレクティブ名。value: ディレクティブに渡される値。例えばv-my-directive="1 + 1"では、value は2です。oldValue:updateとcomponentUpdatedにおいてのみ利用できる以前の値。値が変化したかどうかに関わらず利用できます。expression: 文字列としてのバインディング式。例えばv-my-directive="1 + 1"では、式は"1 + 1"です。arg: もしあれば、ディレクティブに渡される引数。例えばv-my-directive:fooでは、arg は"foo"です。modifiers: もしあれば、修飾子 (modifier) を含んでいるオブジェクト。例えばv-my-directive.foo.barでは、modifiers オブジェクトは{ foo: true, bar: true }です。
vnode: Vue のコンパイラによって生成される仮想ノード。さらに詳しくは VNode API を参照してください。oldVnode:updateとcomponentUpdatedフックにおいてのみ利用できる以前の仮想ノード。
el を除いて、これらの全てのプロパティは読み込みのみ (read-only) で変更しないものとして扱わなくてはいけません。フックを超えてデータを共有する必要がある場合は, 要素の dataset を通じて行うことが推奨されています。
いくつかのプロパティを使用したカスタムディレクティブの例:
<div id="hook-arguments-example" v-demo:foo.a.b="message"></div>
Vue.directive('demo', {
bind: function (el, binding, vnode) {
var s = JSON.stringify
el.innerHTML =
'name: ' + s(binding.name) + '<br>' +
'value: ' + s(binding.value) + '<br>' +
'expression: ' + s(binding.expression) + '<br>' +
'argument: ' + s(binding.arg) + '<br>' +
'modifiers: ' + s(binding.modifiers) + '<br>' +
'vnode keys: ' + Object.keys(vnode).join(', ')
}
})
new Vue({
el: '#hook-arguments-example',
data: {
message: 'hello!'
}
})
動的なディレクティブ引数
ディレクティブの引数は動的にできます。例えば、v-mydirective:[argument]="value" において、argument はコンポーネントインスタンスの data プロパティに基づいて更新されます!これにより、アプリケーション内でのカスタムディレクティブの利用が柔軟になります。
要素をページの固定位置にピン留めするカスタムディレクティブを作りたいとしましょう。縦方向のピクセル位置を値で設定するカスタムディレクティブを次のように作ることができます:
<div id="baseexample">
<p>Scroll down the page</p>
<p v-pin="200">Stick me 200px from the top of the page</p>
</div>
Vue.directive('pin', {
bind: function (el, binding, vnode) {
el.style.position = 'fixed'
el.style.top = binding.value + 'px'
}
})
new Vue({
el: '#baseexample'
})
これにより、ページの上端から 200px の位置に要素を固定できます。しかし、上端からではなく左端からの位置で要素をピン留めしたくなったらどうでしょうか?動的引数はコンポーネントのインスタンス毎に更新できるので、こういう場合に役立ちます:
<div id="dynamicexample">
<h3>Scroll down inside this section ↓</h3>
<p v-pin:[direction]="200">I am pinned onto the page at 200px to the left.</p>
</div>
Vue.directive('pin', {
bind: function (el, binding, vnode) {
el.style.position = 'fixed'
var s = (binding.arg == 'left' ? 'left' : 'top')
el.style[s] = binding.value + 'px'
}
})
new Vue({
el: '#dynamicexample',
data: function () {
return {
direction: 'left'
}
}
})
結果:
このカスタムディレクティブは、ちょっとした違いのユースケースを柔軟にサポートできるようになりました。
関数による省略記法
多くの場合、bind と update には同じ振舞いが欲しいでしょうが、その他のフックに関しては気にかけません。例えば:
Vue.directive('color-swatch', function (el, binding) {
el.style.backgroundColor = binding.value
})
オブジェクトリテラル
あなたのディレクティブが複数の値を必要ならば、JavaScript オブジェクトリテラルも渡すことができます。ディレクティブは任意の妥当な JavaScript 式を取ることができるのを覚えておいてください:
<div v-demo="{ color: 'white', text: 'hello!' }"></div>
Vue.directive('demo', function (el, binding) {
console.log(binding.value.color) // => "white"
console.log(binding.value.text) // => "hello!"
})