LoginSignup
4
3

More than 5 years have passed since last update.

vue.jsのカスタムディレクティブを使ってdata属性を付与する

Last updated at Posted at 2019-01-09

この記事の内容

Webサービス開発でユーザーの行動データを集計するのにGoogle Analyticsを使っています
リンクを踏んだりとかボタンをクリックしたりみたいなものは簡単にかけますが、それをさらに細分化したくなるとdata属性を埋め込むようになると思います

ただ、その時に直接data属性を追加してしまうと、変更箇所や新しい実装のときにdata属性を付け忘れていないか?data属性の記述はtypoしていないか?などを常に意識する必要がでてきます

Vuejsのディレクティブを活用して、上記の問題を軽減してみようという話です

ステップ1: data属性の定義をコンポーネントに含める

Button.vue
<template>
  <button data-category="button" data-action="click">
    Button
  </button>
</template>
index.vue
<template>
  <Button />
</template>
出力.html
<button data-category="button" data-action="click">
  Button
</button>

なにをしたか

Buttonという小さいコンポーネント定義した
data属性の定義をコンポーネントに持たせた

どうなったか

コンポーネントにイベントの情報を持たせたので実装のときにdata属性のことを意識しなくてよい

ステップ2: vueのディレクティブを使用して役割を切り離す

ステップ1の実装で困る状況は、「そのコンポーネント以外でも同じイベント取りたい!」ってなったときにその部分だけいままで通り直接実装することになってしまいます
そこでVuejsのカスタムディレクティブを使うことで特定のdata属性を追加するという処理をButtonから切り離します

data.js
// クリックイベント用のディレクティブ
// クリックイベントを計測したい場合は、このディレクティブを追加してください
Vue.directive('data-action-click', { // v-data-action-clickというディレクティブが追加される
  bind: function (el) { // このelはディレクティブを追加したDOM
    el.setAttribute('data-category', 'button') // data-category="button" というdata属性を追加
    el.setAttribute('data-action', 'click')    // data-action="click" というdata属性を追加
  }
})
Button.vue
<template>
  <button class="btn" v-data-action-click="button"> <!-- この指定だけで2つのdata属性を追加できる -->
    Button
  </button>
</template>
index.vue
<template>
  <div id="app">
    <Button />
    <div class="btn" v-data-action-click> <!-- Button以外でもディレクティブを追加すれば同様に使える -->
      Div
    </div>
  </div>
</template>
出力.html
<button data-category="button" data-action="click">
  Button
</button>
<div class="btn" data-category="button" data-action="click">
  Div
</div>

なにをしたか

v-data-action-clickというディレクティブを追加した

どうなったか

Button以外でも簡単にdata属性を追加できるようになった
data属性を複数追加する必要があるときも、ディレクティブ1つを追加するだけで良い
なので、追加でdata属性を追加するときもディレクティブの定義を修正するだけで作業が終わる

ステップ3: ディレクティブのbindingを使って動的な値も渡せるようにする

ステップ2の実装で困る状況は、「data-action="search"みたいなのを追加したいけどいちいちディレクティブを追加しないとなの?面倒じゃね??」

はい、面倒です、なのでディレクティブフック引数を使いましょう
結構カスタムできます、以下に簡単な実装例を書きます

data.js
// クリックイベント用のディレクティブ
// クリックイベントを計測したい場合は、このディレクティブを追加してください
// v-data-action-click="ここに入れた値がexpressionになる"
Vue.directive('data-action-click', {
  bind: function (el, binding) {
    el.setAttribute('data-category', binding.expression)
    el.setAttribute('data-action', 'click')
  }
})
Button.vue
<template>
  <button class="btn" v-data-action-click="'button'">
    Button
  </button>
</template>
Main.vue
<template>
  <div id="app">
    <Button />
    <div class="btn" v-data-action-click="'div'">
      Div
    </div>
  </div>
</template>
出力.html
<button data-category="button" data-action="click"> <!-- categoryがbuttonになる -->
  Button
</button>
<div class="btn" data-category="div" data-action="click"> <!-- categoryがdivになる -->
  Div
</div>

なにをしたか

ディレクティブのexpressionを受け取ってdata-categoryに設定されるようにした

どうなったか

動的な値を渡せるので、基本形だけディレクティブで作成してしまえばあとは追加で実装する頻度はステップ2よりは少なくなりそう

さいごに

data属性をべた書きするよりは色々と便利だったりメンテナンスコスト低いと思っているのでこんな感じでやってみようかなと思っている最中です
他にやり方やアドバイスなどあればコメントとか編集リクエストとかください

参考

デモ: sample-vue-custom-directive
リポジトリ: sinshutu/sample-vue-custom-directive

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3