💭

【Vue】カスタムディレクティブについて考える

2024/01/28に公開

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

  • Vue.js のフレームワークで提供される機能の 1 つで、HTML 要素に対してカスタムの振る舞いや操作を追加するために使用される。
  • 通常、Vue.js のテンプレート内でデータを表示したり操作したりするために、ディレクティブを使用する。
  • 例えば、v-bind ディレクティブは要素の属性をデータにバインドし、v-on ディレクティブはイベントリスナーを設定する。
  • ユーザ自身が独自のディレクティブを定義することで、再利用性を高めることができる。
  • 名前は”v-”で始まる。

公式ドキュメント
https://vuejs.org/guide/reusability/custom-directives.html#custom-directives

compositionAPI での書き方

公式ドキュメントを見ると、compositionAPI では以下のようにカスタムディレクティブを定義できることがわかる。
・ディレクティブ名を小文字の v から始める
・キャメルケースで記述する(例:vHogeFuga)
・template 内の要素には v-hoge-fuga の形式で記述する

<script setup>
// enables v-focus in templates
const vFocus = {
  mounted: (el) => el.focus(),
};
</script>

<template>
  <input v-focus />
</template>

使用例

例えば下記のように書くこともできる。

<script lang="ts" setup>
const vBlueBackground = {
  mounted: (el: HTMLElement) => (el.style.background = "blue"),
};
</script>

<template>
  <div v-blue-background>青い背景</div>
</template>

このコードでは、ある要素の背景色を青にしている。
しかし、背景を青にするだけであれば class を使用すれば良いし、カスタムディレクティブをわざわざ作成する必要もない。
ではどんな時に使用するのがいいのだろうか。

使用シーンについて考えてみた

ドキュメントを読んでみると次のような記載がある。

なるほど、DOM を直接操作することでしか機能を実現できない場合にのみ使用するのか。
そして可能な限り組み込みのディレクティブを使用しろと。
イマイチよくわからない。

ここで再度ドキュメントを読み返すとこんなことが書いてあった。

赤線部分を見るにカスタムディレクティブを使うことの優位性は、vue によって動的に作られた要素にも対応できることであるのだろう。

実際に検証してみた

下記のコードにて実際に検証してみた。
ボタンを押すことでカスタムディレクティブで autofocus を設定した要素と、属性で autofocus を設定した要素を切り替えて表示させてみる。

<script lang="ts" setup>
const isShowNoCustomInput = ref(false);
const isShowCustomInput = ref(false);

const showNoCustomInput = () => {
  isShowCustomInput.value = false;
  isShowNoCustomInput.value = true;
};

const showCustomInput = () => {
  isShowNoCustomInput.value = false;
  isShowCustomInput.value = true;
};

const vFocus = {
  mounted: (el: HTMLElement) => el.focus(),
};
</script>

<template>
  <div style="margin: 100px 0 0 100px">
    <button style="border: 1px solid black" @click="showNoCustomInput">
      showNoCustomInput!
    </button>
    <button
      style="border: 1px solid black; margin-left: 20px"
      @click="showCustomInput"
    >
      showCustomInput!
    </button>
    <div v-if="isShowNoCustomInput">
      <input type="text" autofocus placeholder="isShowNoCustomInput" />
    </div>
    <div v-if="isShowCustomInput">
      <input type="text" v-focus placeholder="isShowCustomInput" />
    </div>
  </div>
</template>

autofocus 属性の表示

表示させてみると確かに focus はされていない。

カスタムディレクティブによる表示

うん、focus されている。

まとめ

カスタムディレクティブは setup だと簡単に設定することができる。
使用シーンとしては、動的に生成された要素に対して DOM レベルで操作したい時に使う。
アニメーション設定するとかも使えそう。
他にもこんな使い方いいよって方は教えてください!

Discussion