[Vue.js] コンポーネントの色をコンポーネントの外側から指定する方法

CSS, HTML, JavaScript, Vue.js, Web

もくじ


どんな場合に必要か

あるコンポーネントで、使いみちによって色だけ変えたい場合がある。

例えばボタン。

ボタンと一口にいっても、使いみちには色々ある。

  • 重要なボタン。このボタンを押すと、ユーザーが入力した情報がデータベースに上書き保存される。後戻りできない。
  • 普通のボタン。このボタンを押すと、モーダルダイアログが表示されるなどの動作をする。
  • あまり重要でないボタン。このボタンを押すと、参考情報が表示されるなどの動作をする。

などなど。

このように、使いみちによってコンポーネントの色を変えるなどして、ユーザーにさりげなく思考や操作を誘導できたりする。その結果、「このソフトは直感的に操作できる」となったりする。


実現方法は大きく2通り。(他にもあるかも、教えて詳しい人)

1つ目:HTMLテンプレートに設定する属性で色を指定する方法

実現するイメージ

コンポーネントにあらかじめ決めておいた属性を追加することで、色を指定する方法。

例えば次のように指定する。

<my-button color-blue>ボタンA(青)</my-button>
<my-button color-white>ボタンA(白)</my-button>
<my-button color-gray>ボタンA(灰)</my-button>

実現方法

HTMLでは、値の無い属性が指定された場合、その属性は値trueとして処理される。

例えば、

<my-button color-blue></my-button>

とすると、color-blue属性は値trueとして処理される。

一方で、

<my-button></my-button>

のように属性を指定しないと、値falseとして処理される。

この性質を使う。

まず、Vueコンポーネントにpropsを追加する。

先ほどのmy-buttonの例では次の要領で3つのpropsを追加する。

  props: {
    colorBlue: {
      type: Boolean,
      required: false,
      default: false,
    },
    colorWhite: {
      type: Boolean,
      required: false,
      default: false,
    },
    colorGray: {
      type: Boolean,
      required: false,
      default: false,
    },
  },

ポイントは、いずれもBoolean型であり、既定値がfalseであること。

次に、このpropsの値に応じてコンポーネントの色を設定する処理をつくる。

次の要領で、CSSスタイルを返すcomputedを1つ用意する。

  computed: {
    buttonStyle: {
      get() {
        let buttonBgColor = "blue";
        let buttonColor = "white";
        if (this.colorWhite) {
          buttonBgColor = "white";
          buttonColor = "black";
        }
        if (this.colorGray) {
          buttonBgColor = "gray";
          buttonColor = "white";
        }
        return `background-color: ${buttonBgColor}; color: ${buttonColor};`;
      },
    },
  },

これを、HTMLテンプレートで使う。

<template>
  <button :style="buttonStyle">
    <slot></slot>
  </button>
</template>

最終的にコンポーネントは次のような作りになる。

<template>
  <button :style="buttonStyle">
    <slot></slot>
  </button>
</template>

<script>
export default {
  computed: {
    buttonStyle: {
      get() {
        let buttonBgColor = "blue";
        let buttonColor = "white";
        if (this.colorWhite) {
          buttonBgColor = "white";
          buttonColor = "black";
        }
        if (this.colorGray) {
          buttonBgColor = "gray";
          buttonColor = "white";
        }

        return `background-color: ${buttonBgColor}; color: ${buttonColor};`;
      },
    },
  },
  name: "MyButton",
  props: {
    colorBlue: {
      type: Boolean,
      required: false,
      default: false,
    },
    colorWhite: {
      type: Boolean,
      required: false,
      default: false,
    },
    colorGray: {
      type: Boolean,
      required: false,
      default: false,
    },
  },
};
</script>

2つ目:HTMLテンプレートに設定するクラスで色を指定する方法

実現するイメージ

コンポーネントにあらかじめ決めておいたクラスを指定することで、色を指定する方法。

例えば次のように指定する。

<my-button class="button-blue">ボタンB(青)</my-button>
<my-button class="button-white">ボタンB(白)</my-button>
<my-button class="button-gray">ボタンB(灰)</my-button>

実現方法

コンポーネントに直接指定されたクラスは、コンポーネントのHTMLテンプレートの最上位タグに設定される。

例えば、

<my-button class="button-blue"></my-button>

のようにbutton-blueクラスが指定され、

コンポーネントのHTMLテンプレートが

<template>
  <button>
    <slot></slot>
  </button>
</template>

であった場合、button-blueクラスはtemplateタグ直下のbuttonタグに設定される。

この性質を使う。

といってもコンポーネント側の実装はごくごく簡単で、次のようにスタイルを用意しておくだけだ。

<template>
  <button>
    <slot></slot>
  </button>
</template>

<script>
export default {
  name: "MyButton",
};
</script>

<style>
button.button-blue {
  background-color: blue;
  color: white;
}
button.button-white {
  background-color: white;
  color: black;
}
button.button-gray {
  background-color: gray;
  color: white;
}
</style>

2つの方法の比較

比較項目属性で色を指定する方法クラスで色を指定する方法
コンポーネントのコード量
コンポーネント利用側のコード量
コンポーネント利用側のコードの可読性
コード整形しやすい
スタイルの保守性
コンポーネント利用側のデバッグのしやすさ
クラス指定の誤字などに気付きにくい