Vueで開発するときのプラクティス!メンテナンス性の高いコードを書こう

Vue.jsやっていますか?

仕事でもプライベートでもばかり他のライブラリを使わなくなるくらい集中的にVueを触っているうちに自分なりのプラクティスが固まってきました。

わかりやすくメンテナンスしやすいVueのコードを書くためにやったほうが良いことを紹介します。

変数とメソッド名に命名規則を設ける

変数やメソッドには種類があるため命名規則を設けるコードで読みやすくわかりやすいコードを実現することができます。

Booleanが入る変数はis○○

trueもしくはfalseが入る変数の先頭には「is」をつけるようにします。

たとえば表示を切り替えるようなものであればisShowのようになります。

<div v-if="isShow">
  isShowがtrueなら表示される
</div>

単にshowよりもisがついていることでBooleanの値が入っていることがひと目でわかり理解しやすくありませんか?

onEvent名○○

メソッド名はon + イベント名 + メソッド名のようにします。

たとえばクリック時に呼ばれるメソッドの場合は下記のようなコードです。

<template>
  <button @click="onClickOk">OK</button>
</template>

<script>
export default {
  methods: {
    onClickOk() {

    }
  }
}
</script>

このルールに乗っ取るとメソッドはすべて頭にonがつくことになります。

イベントはなく別のコンポーネントのイベントからコールバックとして呼ばれるものはonCreateやonCreatedのようにイベント名は省略します。

コンポーネント内で変動するUIの状態以外の値はformオブジェクトでまとめる

vueでは変動する値はdataで管理することができます。

data内にはUIの状態を表すものやinputの値など、用途が違うものが置かれます。

そこで違いを分かりやすくするためにinputやtextareaなど、データ更新などでAPIにリクエストを送るようなものはformというオブジェクトにいれてしまうとコードがぐんと分かりやすくなります。

先に紹介した命名規則も取り入れたサンプルのコードは下記です。

<template>
  <div>
    <div v-if="isAlert">
      formの説明文
      <a href="#" @click.prevent="onClickCloseAlert">close</a>
    </div>
    <div><input type="text" v-model="form.name"></div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isAlert: true,
      form: {
        name: ''
      }
    }
  },
  methods: {
    onClickCloseAlert() {
      this.isAlert = false
    }
  }
}
</script>

styleタグに必ずscopedをつける

vueファイルではstyleタグを使うことができますが、必ずscoped属性をつけるようにします。

scoped属性をつけることで定義したスタイルはコンポーネント内のみに有効になります。

<style scoped>

</style>

コンポーネント内でscoped属性をつけずに実装してしまうと、グローバルなCSSになってしまいます。

そのためあっという間に破綻して触るのが苦痛になるコードが出来上がってしまうため、scoped属性はメンテナンスしやすいコードを書くのに必要不可欠です。

v-elseは使用しない

vueでifを使うにはv-ifとv-elseを使うことができます。

公式のドキュメントでもv-elseは使われていますが、使わないほうがわかりやすいのではないかと思っています。

まずv-ifとv-elseの使用例は下記です。

<div v-if="isTrue">
  isTrueがtrueの場合
</div>
<div v-else>
  isTrueがfalseの場合
</div>

v-ifの後続のタグにv-elseをつけることで、v-ifがfalseの場合のテンプレートを表示することができます。

v-elseを使わないほうが良いと思っている理由はテンプレートが大きくなった場合v-ifとv-elseの関係性が読みづらいからです。

テンプレートは小さく保つのが理想ですが、どうしても大きくなってしまう場合もあります。

v-elseは使わずに下記のコードのようにv-ifだけ実装している方がブロックの塊ごとに条件がついていて読みやすいように思います。

<div v-if="isTrue">
  isTrueがtrueの場合
</div>

<div v-if="!isTrue">
  isTrueがfalseの場合
</div>

Vuex

アクションはdispatchで呼ぶ

Vuexではアクションを任意のメソッド名で呼べるようにするヘルパーが用意されています。

import { mapActions } from 'vuex'

{
  methods: {
    ...mapActions({
      hello: 'messages/hello' // this.$store.dispatch('messages/hello')をthisにバインド
    })
  }
}

上記のようにすることで本来はthis.$store.dispatch('messages/hello')で呼び出すところをthis.hello()にすることができます。

動作上はもちろん問題ありませんが個人的にはmapActionsはバッドパターンだと考えています。

その理由は後からコード読むとき、または他人がコードを読むときに分かりづらいからです。

コードを読めばhelloというメソッドはバインドされたものと理解することはできます。

ですがhelloというメソッドが出てきた時に確認するのはかなり手間です。

  • mapActionsで定義されたものなのか
  • どのストアのどのアクションなのか

mapActionsの定義と呼び出している部分が1画面に収まっているならまだしも、コードが長くなるとこれが大変です。

メソッドが呼び出しているところから定義されているコードを見に行き、また呼び出しの部分に戻ってくるというのは非常にストレスがたまります。

はじめからdispatchが使われていればひと目でどのストアのどのアクションなのか理解できますし、mapActionsを使うためのコードも書く必要がありません。

正直なところmapActionsはデメリットはあっても、メリットあるかな?という印象を持っています。

さいごに

Vue.jsはシンプルで触りやすいフレームワークである一方で、適当にコードを書いても結構動いてしまいます。

メリットでありデメリットにもなるため分かりやすくメンテナンス性を高めるためにはある程度のルールを設けたほうが良いと思っています。

今回紹介したコードで分かりやすい!と共感いただけるものがあれば取り入れてみてはいかがでしょうか?

コウジ
Vue.jsが好きなフリーランスのフロントエンドエンジニアです。 フロントのHTML・CSS・JavaScriptの設計実装をメインに、RubyとNodeでサーバーサイドやってたりもします。