Help us understand the problem. What is going on with this article?

ワイ「何でそんな小っさいコンポーネント作ってるん?w」

とあるWeb制作会社にて

ワイ「ハスケル子ちゃん」

ハスケル子「はい」

ワイ「今日ワイは何の仕事するんやったっけ?」

ハスケル子「確か今日からは」
ハスケル子「NuxtVuetifyを使って管理画面を作る案件が始まるんじゃなかったでしたっけ?」

ワイ「おお、せやった」

ハスケル子「もうFigmaのデザイン見ましたか?」

ワイ「ヒグマ?」
ワイ「ヒグマなんて、写真でしか見たことないけど」

ハスケル子「Figmaです」
ハスケル子「ブラウザ上でも使えるデザインツールですよ」

ワイ「ああ、そっちな」
ワイ「Higumaのほうね」

ハスケル子「じゃあ、さっそくデザイン見ながら」
ハスケル子「コーディングしていきましょう」

ワイ「おお、頑張っていこか!」

デザインを見てみる

スクリーンショット 2020-06-21 17.31.00.png

ハスケル子「↑このキャンセルボタンOKボタン」
ハスケル子「いろんなページで使うみたいなので」
ハスケル子「OkButtonCancelButtonて感じで」
ハスケル子「それぞれコンポーネントとして作っておきましょうか」

ワイ「ん?コンポーネント作る?」
ワイ「でも今回は、Vuetifyっていうコンポーネントフレームワークを導入してるから」
ワイ「Vuetifyのv-btnっていうコンポーネントを使えばええんちゃう?」

<v-btn>
  キャンセル
</v-btn>
<v-btn>
  OK
</v-btn>

ワイ「↑こんな感じや」
ワイ「あとはいくつかpropsを指定してやれば、デザイン通りの見た目になるで」

ワイ「丸いボタンやからrounded
ワイ「影はいらんからdepressed
ワイ「長さを揃えたいからmin-width="120"
ワイ「大きめにしたいからlarge
ワイ「他にも色々・・・」
ワイ「あとは、クリックイベントつけて・・・」

<v-btn
  rounded
  depressed
  min-width="120"
  large
  outlined
  @click="cancel"
>
  キャンセル
</v-btn>
<v-btn
  rounded
  depressed
  min-width="120"
  large
  color="primary"
  @click="ok"
>
  OK
</v-btn>

ワイ「↑こんな感じや」

ハスケル子「でも、毎回こんなにprops書いてたら」
ハスケル子「面倒くさいじゃないですか」
ハスケル子「OkButtonCancelButtonていうコンポーネント作りましょうよ」

ワイ「別に、コピペするだけやん」
ワイ「何でわざわざ、v-btnを1つ入れるためだけのコンポーネントを作らなあかんねん」

ハスケル子「そんなに言うなら、コンポーネント化しなくてもいいですけど・・・」

4時間後

ワイ「ふう、だいぶコーディングが進んだな」
ワイ「2人で100ページもできたで」

ハスケル子「私が99ページで、やめ太郎さんは1ページですけどね」

ワイ「ま、まぁな」

社長「おーい」
社長「やめ太郎、ハスケル子ちゃん」

ワイ「何でっか」

社長「ちょっとデザイン変わるらしいわ」
社長「丸っぽいボタンやなくて、四角いボタンに変わるみたいや」

スクリーンショット 2020-06-21 18.14.11.png

社長「↑こんな感じや」

ワイ「ファッ!?
ワイ「もう100ページもコーディングしてしまいましたが!?」

ハスケル子「(やめ太郎さんは1ページ・・・)」

ワイ「まあ、検索置換でroundedを消せばいいだけか・・・」
ワイ「roundedというpropsを消せば、丸みがなくなるからな」
ワイ「よっしゃ、さっそく検索置換や!」
ワイ「・・・アッ!なんかエラー出た!」

ハスケル子「なんか、消しちゃいけないroundedも消しちゃったみたいですね」

ワイ「ぐぬぬ」
ワイ「割とありふれた単語やから、慎重に検索置換せんとな・・・」

ハスケル子「その必要はないですよ」

ワイ「えっ・・・何で・・・」

実はコンポーネント作ってました

ハスケル子「実は、OkButtonCancelButtonていうコンポーネント」
ハスケル子「私が作っておきました」
ハスケル子「私がコーディングした99ページでは、そのコンポーネントを使ってます」

ワイ「そ、そうなんか」

<CancelButton @click="cancel" />
<OkButton @click="ok" />

ハスケル子「↑こんな感じです」

ワイ「おお、スッキリやね」

ハスケル子「OkButtonコンポーネントの中身は↓こんな感じです」

/components/OkButton.vue
<template>
  <v-btn
    rounded
    depressed
    min-width="120"
    large
    color="primary"
    @click="$emit('click')"
  >
    OK
  </v-btn>
</template>

ワイ「ただv-btnをラップしただけのコンポーネントな訳やね」

ハスケル子「はい」
ハスケル子「このOkButtonコンポーネントのroundedを消して」
ハスケル子「CancelButtonコンポーネントからもroundedを消す」
ハスケル子「たった2ファイルを編集するだけで」
ハスケル子「99ページ全てのボタンが、丸から四角に変わります」

ワイ「ほんまやん・・・!」

ハスケル子「ボタン1つだけでも、コンポーネント化しておいて良かったですね」

ワイ「ぐぬぬ」
ワイ「いや、でもコンポーネント化すると」
ワイ「それを読み込むためのコードを全ページに書かんとあかんやん?」

  components: {
    CancelButton,
    OkButton
  },

ワイ「↑こんな感じで」

ハスケル子「書かなくても大丈夫ですよ」
ハスケル子「ちょっとした設定をするだけです」

ワイ「」

ハスケル子「小さいコンポーネントにだって、ちゃんと価値があるんです」
ハスケル子「やめ太郎さんの小さい脳ミソにも価値があるように」

ワイ「せやな」
ワイ「ありがとう、ハスケル子ちゃん・・・!」

もっと小さいコンポーネントも作ってた

ハスケル子「実はこんなコンポーネントも作りました」

/components/Heading2.vue
<template>
  <h2 class="heading2">
    <slot />
  </h2>
</template>

ワイ「こ、これは・・・」
ワイ「実質h2タグだけやん」
ワイ「何でそんな小っさいコンポーネント作ってるん?w

ハスケル子「だって、この見出しも」
ハスケル子「ほとんど全ページで登場するパーツじゃないですか」

ワイ「いや、でも・・・」

<h2 class="heading2">見出し</h2>

ワイ「普通に↑こう書けばいいだけやん」
ワイ「もし、さっきのボタンみたいにデザイン変更が発生したとしても」
ワイ「CSSで調整すればええだけやで」
ワイ「さすがにこのコンポーネントは無意味やろ・・・w」

ハスケル子「チッ」

社長「おーい」
社長「またデザイン変わったわ」
社長「見出しのデザインが、ちょっと凝った感じになったわ」
社長「でも、h2タグの中にspanタグでも入れれば実現可能やろ」

ワイ「ファッ!?
ワイ「全ページのh2タグの中にspan入れなアカンの!?」

ハスケル子「だから必要ないですって」

/components/Heading2.vue
<template>
  <h2 class="heading2">
    <span>
      <slot />
    </span>
  </h2>
</template>

ハスケル子「↑こうです」
ハスケル子「さっきのHeading2コンポーネントの中にspanタグを書くだけです」

ワイ「おお・・・」
ワイ「小さなパーツでもコンポーネントにしておくと、修正するときにラクなんやな・・・」

ハスケル子「はい」
ハスケル子「しかも、コンポーネント化することで」
ハスケル子「グローバルなCSSじゃなくscopedにできるじゃないですか」

ワイ「あー、せやな」
ワイ「グローバルなCSSって、修正すると予想外のところに影響が出ちゃったりするもんな」

ハスケル子「そうなんです」
ハスケル子「やめ太郎さんは無意味だとか言ってましたけど」
ハスケル子「この説明をする時間の方が、よっぽど・・・」

ハスケル子「無意味です。」

ワイ「あ、あんまりいじめんといてや・・・」

〜おしまい〜

まとめ

  • かなり小さいパーツでもコンポーネント化しておくことで、修正コストを削減できた。
  • コンポーネント化すると、CSSもグローバルじゃなくできるから(scoped)影響範囲がコントロールできて良いよね。

さらに

  • OkButtonCancelButtonのpropsがほとんど共通なので、まずはBaseButtonというコンポーネントを作って、それを元に2つのコンポーネントを作るとなお良し。
  • ベースコンポーネント・基底コンポーネントってやつですね。
  • v-bind="$attrs"を使って、親から受け取ったpropsを全てv-btnに渡すようにしておくと「ここだけちょっと違うprops渡したい!」ってときにも対応できるで!

前にTwitterでアンケートしたときの結果

私も以前は「小さいコンポーネントって要るの?」派でしたが、最近は小さくても作ってもいいかなって思ってます。

yumemi
みんなが知ってるあのサービス、実はゆめみが作ってます。スマホアプリ/Webサービスの企画・UX/UI設計、開発運用。Swift, Kotlin, PHP, Vue.js, React.js, Node.js, AWS等エンジニア・クリエイターの会社です。東京(三軒茶屋)/京都(四条烏丸)/札幌/大阪/福岡に展開中!Twitterで情報配信中https://twitter.com/yumemiinc
http://www.yumemi.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした