(Sample)
Vue.jsを使って、よくある「星(スター)評価」のUIコンポーネントを作るサンプルコードを、新人エンジニア向けにわかりやすく解説していきます!
飲食店のレビューやアプリの評価など、星評価のUIはさまざまなサービスで活用されていますよね?このチュートリアルでは、Vueのコンポーネント設計・イベント伝達・バインディングの基本まで一気に学べます!
実現できる機能とは?
まずは完成イメージを言葉で確認しましょう。
- ⭐ 星マークが5つ表示される
- ⭐ マウスでクリックした位置まで「金色」に変化
- ⭐ クリックされた星数が「評価値」として表示される
HTML構造の確認
Vue.jsが使われているので、HTML側にはVueインスタンスのマウント先として id="app"
が指定されています。
<div id="app" class="container mt-5">
<h1 class="mb-4">{{ title }}</h1>
<star-rating :rating="rating" @set-rating="setRating"></star-rating>
<p class="mt-3">現在の評価: {{ rating }} 星</p>
</div>
{{ title }}
:Vueのデータバインディングでタイトルを表示<star-rating>
:カスタムコンポーネント:rating="rating"
:親 → 子へ値を渡す(Props)@set-rating="setRating"
:子 → 親へイベント通知(カスタムイベント)
Vueコンポーネントでスター評価を定義
Vue.component("star-rating", {
props: ["rating"],
template: `
<div class="star-rating">
<span v-for="star in 5" :key="star" class="fa fa-star"
:class="{ 'checked': star <= rating }"
@click="setRating(star)"></span>
</div>
`,
methods: {
setRating(star) {
this.$emit("set-rating", star);
},
},
});
ポイント解説
v-for="star in 5"
:5つの星をループで表示:class="{ 'checked': star <= rating }"
:条件付きクラス適用で色を変える@click="setRating(star)"
:クリックされたときの処理this.$emit()
:子コンポーネントが親にイベント通知するためのメソッド
親インスタンス側の設定
new Vue({
el: "#app",
data: {
title: "Vue.jsとスター評価のサンプル",
rating: 0,
},
methods: {
setRating(star) {
this.rating = star;
},
},
});
data
に評価値(rating
)を保持setRating
メソッドで、子から送られてきた星の数を更新- 結果として
<p>
に「現在の評価:X星」とリアルタイムで反映される
スタイル設定
.star-rating .fa-star {
cursor: pointer;
font-size: 2rem;
color: #ddd;
}
.star-rating .fa-star.checked {
color: gold;
}
- 通常は薄いグレー(
#ddd
) checked
クラスが付くとゴールドに!
よくある質問:Q&A
Q. 評価を半分(3.5など)にできますか?
A. このコードでは整数のみですが、fa-star-half-alt
を使えば0.5刻み評価も可能です。
Q. 星の数を10個にしたいときは?
A. v-for="star in 10"
に変更するだけでOK!
Q. 初期評価を表示したいときは?
A. data: { rating: 3 }
などとすれば、最初から3つ星が付きます。
今後の学習の指針
このスター評価コンポーネントを理解したら、次のステップに進みましょう!
- リアクティブなフォームとの連携(v-modelの使い方)
- 動的なPropsと双方向バインディング
- 評価値をバックエンドに送信(Axiosやfetch)
- Vue 3 Composition APIによる書き換え
- アニメーションで評価感を出す(CSS Transitions)
Vue.jsを使えば、「動的でわかりやすいUI」を簡単に実装できます。スター評価はその入口として最適!ぜひ自分なりに改造して、体で覚えてください。応援しています!