【Vue.js】カスタムディレクティブを使う

ディレクティブとは、v-から始まるVueが提供しているパーツの事です。
Vueが提供しているディレクティブについてはこちら↓


Vueが提供してくれているもの以外でも、自分でv-を作成することができます。
主に、抽象化したコードを再利用したい時に使われます。
今回の記事では、自分で作るディレクティブについて書いていきます。

スポンサーリンク

カスタムディレクティブを作る

main.jsにカスタムディレクティブを登録する。
Vue.directiveの第1引数にはカスタムディレクティブの名前。第2引数にはオブジェクトを作成してフック関数を5つ書く。
5ないとダメということではない。後述するそれぞれのフック関数の動作に合わせて用いる。

Vue.directive(“[第1引数]”,{第2引数(フック関数)});

Vue.directive("hello",{
  bind() {

  },
  inserted() {

  },
  update() {

  },
  componentUpdated() {

  },
  unbind(){
    
  }
});

それぞれのフック関数について

※赤字は各メソッドに入れることができる引数
bind( el,binding,vnode ){}・・・ディレクティブが初めて要素に紐付いたタイミングで処理したい時。最初の一回しか呼ばれない。

inserted( el,binding,vnode ) {}・・・親Node(DOM)に挿入されたタイミングで処理をしたい時。

update( el,binding,vnode,oldVnode ){}・・・コンポーネントの中身が更新されたタイミングで処理したい時。子コンポーネントの仮想Nodeが更新される前に実行される。

componentUpdated( el,binding,vnode,oldVnode ) {}・・・ コンポーネントの中身が更新されたタイミングで処理したい時。 子コンポーネントの仮想Nodeが更新された後に実行される。

unbind( el,binding,vnode ){}・・・ディレクティブが紐付いている要素から解放された時。

それぞれの引数には、 el,binding,vnodeを入れることができる。updateとcomponentUpdatedにはoldVnode引数を持つことができる。

基本的には、bindとupdateを使う。

bindとupdateを省略して書く

bindとupdateはほぼ同じコードを書くため、Vueが省略してくれる機能がある。

省略して書くには、オブジェクトでフックを書いていったが、オブジェクトではなく 第2引数に function関数をかいていく。

Vue.directive("hello",function(el,binding){});

引数のelはDOMの操作ができる。

Vue.directive("hello",function(el,binding){
  el.style.color = "red";
});

引数のbindingは値を受け渡す事ができる。

<template>
  <div>
    <p v-hello="'blue'">Hello</p>
  </div>
</template>
Vue.directive("hello",function(el,binding){
  el.style.color = "red";
  el.style.color = binding.value;
});

複数のデータを受け渡したい時は、オブジェクトとして受け渡しを行う。

<p v-hello="{fontSize:'50px', color:'blue'}">Hello</p>
Vue.directive("hello",function(el,binding){
  el.style.color = "red";
  el.style.fontSize = binding.value.fontSize;
  el.style.color = binding.value.color;
});

カスタムディレクティブで引数を使う

ディレクティブの引数はひとつだけとることができる。
下記では、引数にborderStyleのsolidを渡して、mainで受け取った。

引数は、ディレクトリーに続けて記載する。
v-hello:solid=

<p v-hello:solid="{fontSize:'50px', color:'blue'}">Hello</p>

ディレクティブ引数の受け取り方は、
binding.arg
で行う。

Vue.directive("hello",function(el,binding){
  el.style.color = "red";
  el.style.fontSize = binding.value.fontSize;
  el.style.color = binding.value.color;
  el.style.border = binding.arg;
});

カスタムディレクティブに修飾子を使う

修飾子はドット(.)でつなげる事ができる。
v-hello:solid.shadow
下記では、修飾子を使ってboxShadowを適用させる。

<p v-hello:solid.shadow="{fontSize:'50px', color:'blue'}">Hello</p>

修飾子を呼び出す時は、if文を使用して修飾子が選択されているかを判別させるコードを書く。
if(binding.modifiers.shadow)では、boolean型が戻ってくる。

Vue.directive("hello",function(el,binding){
  el.style.color = "red";
  el.style.fontSize = binding.value.fontSize;
  el.style.color = binding.value.color;
  el.style.border = binding.arg;
  if(binding.modifiers.shadow){
    el.style.boxShadow = "0 3px 3px black"
  }
});

修飾子はいくつもつなげる事が可能
下記では、boxShadowとtextShadowを追加。

<p v-hello:solid.shadow.textShadow="{fontSize:'50px', color:'blue'}">Hello</p>
Vue.directive("hello",function(el,binding){
  el.style.color = "red";
  el.style.fontSize = binding.value.fontSize;
  el.style.color = binding.value.color;
  el.style.border = binding.arg;
  if(binding.modifiers.shadow){
    el.style.boxShadow = "0 3px 3px black"
  }
  if(binding.modifiers.textShadow){
    el.style.textShadow = "0 3px 3px black"
  }
});

ローカルにカスタムディレクティブを登録する

上記まででは、グローバル登録をしてきましたが、今回はローカルに登録する方法を記載します。

directivesオプションを使う。
※ES6の書き方をしているためfunctionは省略されている。

<script>
export default {
  directives: {
    hello(el, binding) {
  }
};
</script>

オブジェクトの中はグローバル登録の時と同じ書き方をする。
全体のコードはこちら。

<template>
  <div>
    <p v-hello:solid.shadow.textShadow="{fontSize:'50px', color:'blue'}">Hello</p>
  </div>
</template>

<script>
export default {
  directives: {
    hello(el, binding) {
      el.style.color = "red";
      el.style.fontSize = binding.value.fontSize;
      el.style.color = binding.value.color;
      el.style.border = binding.arg;
      if (binding.modifiers.shadow) {
        el.style.boxShadow = "0 3px 3px black";
      }
      if (binding.modifiers.textShadow) {
        el.style.textShadow = "0 3px 3px black";
      }
    }
  }
};
</script>

カスタムディレクティブの中でthisを使用することができないので気をつける。

タイトルとURLをコピーしました