普段Vuetify
やIonic
とったコンポーネントライブラリを使うのに慣れてるから、コンポーネント間のデータのやり取りやイベントは書ける。
けど、それをどうスタイルに紐付ければいいのか分からないってことありませんか?
<DemoButton color="primary" large icon outlined />
上記の
- color
- large
- icon
- outlined
っていう4つのprops
をどうスタイルに紐づけるか?
スタイルも意識したコンポーネントの作成をしてみましょう。
TL;DR
color
のようにを値の種類が複数あるものは style
で上書き
outlined
のようにtrue/falseの真偽値で表せるものは class
を付与
コンポーネントの全体コード
動作環境としてはTypeScript化したNuxt.jsですが、概念を伝えるのが目的なので環境設定等は省略します。悪しからず。
DemoButton.vue
<template>
<button type="button" :class="classes" :disabled="disabled" :style="styles">
<slot></slot>
</button>
</template>
<script lang="ts">
import Vue from "vue";
export default Vue.extend({
name: "DemoButton",
props: {
color: {
type: String,
required: false,
default: "primary"
},
disabled: {
type: Boolean,
required: false,
default: false
},
outlined: {
type: Boolean,
required: false,
default: false
}
},
computed: {
styles () {
//validateColorは @/assets/scss/_variable.scss で定義した色が指定されているかどうか確かめる為に作った関数
return {
'--color': validateColor(this.color),
}
},
// バインドするクラスを生成
classes() {
return {
"demo-btn": true,
"demo-btn--outlined": this.outlined
};
}
}
});
</script>
<style lang="scss" scoped>
.demo-btn {
// デフォルトの背景色
--color: yellow;
// CSS変数を背景色に割り当て
background-color: var(--color);
}
.demo-btn--outlined {
position: relative;
display: inline-block;
box-sizing: border-box;
border: solid 1px;
border-radius: 4px;
background-color: transparent;
}
</style>
値のパターンをを複数もつprops
上記のコードで言うと color
が該当します。
この引数は
- primary
- secondary
- green
- error
など様々な文字列を取る可能性があります。なのでこの場合は、
引数で指定された値を後からstyle
属性で上書きする
という方法を使います。
.demo-btn {
// デフォルトの背景色
--color: yellow;
// CSS変数を背景色に割り当て
background-color: var(--color);
}
CSS変数でデフォルト値を設定しておき
<button type="button" :class="classes" :disabled="disabled" :style="styles">
styles () {
/*validateColorは @/assets/scss/_variable.scss
で定義した色が指定されているかどうか確かめる為に作った関数*/
return {
'--color': validateColor(this.color),
}
}
style属性に後から代入して上書きしています。
値が真偽値の2パターンしかないprops
こちらは簡単です。
引数が指定された場合のみそれに対応するクラスをコンポーネントに付与するだけです。
<button type="button" :class="classes" :disabled="disabled" :style="styles">
<script lang="ts">
props: {
outlined: {
type: Boolean,
required: false,
default: false
}
classes() {
return {
"demo-btn": true,
"demo-btn--outlined": this.outlined
};
}
</script>
<style lang="scss" scoped>
.demo-btn {
// ...
}
.demo-btn--outlined {
// ....
}
</style>
最後に
コンポーネントライブラリを作ってみよう!ってなっても、スタイルどうすればいいの?って人に少しでも参考になれば幸いです。
参考ページのリンクを貼っておきます