iT邦幫忙

2026 iThome 鐵人賽

DAY 8
0
Modern Web

微光採集瓶:用 Vue 3 打造每日美好記錄網頁系列 第 8 篇

【Day 8】 為今日心情選一個代表色!事件處理 v-on 與 @click

  • 分享至 

  • xImage
  •  

昨天我們把瓶子整理成了獨立的 GemJar.vue 元件。不過目前的「放入」按鈕非常單調,點下去只有數字 +1。生活每天都有不同起伏,有時候平靜、有時候雀躍,你可以自己定義每個顏色代表怎麼樣的心情,如果每一次採集,都能依照今天的心情挑選一個代表色,這個採集瓶就會有客製化的感覺。

今天我們要在按鈕上方加入一組「心情調色盤」,並學會 Vue 處理使用者互動的核心工具:v-on 與 @click 的參數傳遞。

一、認識事件監聽:v-on 與縮寫 @

在原生 JavaScript 裡,要讓按鈕感應用戶點擊,通常會寫 addEventListener('click', ...);但在 Vue 裡面,所有事件監聽都由 v-on 負責。

1. 簡寫規則:直接用 @

就像 Day 6 學過 v-bind:class 簡寫成 :class 一樣,v-on:click 也有官方推薦的簡寫——@click:

  • 完整寫法:<button v-on:click="addGem">放入</button>
  • 簡寫寫法:<button @click="addGem">放入</button>

只要在 HTML 屬性前看到一個 @,就代表「當這個事件觸發時,請去執行指定的 JavaScript 動作」。

2. 傳遞自訂參數:讓函式知道你選了哪種心情

在 Day 4 寫的 addGem 函式中,我們不需要傳入任何資訊,因為它單純只做 count.value++:

<button @click="addGem">放入</button>

但如果畫面上有好幾個不同的心情顏色按鈕,點擊時函式就必須知道「使用者究竟點擊了哪一個顏色」。這時候就可以在括號裡傳入自訂參數:

<button @click="selectColor('#64B5F6')">平靜(藍)</button>
<button @click="selectColor('#E3B341')">驚喜(金)</button>

在 <script setup> 裡只要宣告對應的參數去接收它即可:

function selectColor(color) {
  selectedColor.value = color
}

二、動手做:在 GemJar.vue 加入心情調色盤

打開 src/components/GemJar.vue,進行以下三步驟的修改。

1. <script setup>:記錄當前選擇的心情顏色

我們新增一個 selectedColor 變數來記錄目前挑選的顏色,預設先給溫暖的金色:

import { ref } from 'vue'

const count = ref(0)
const isGlowing = ref(false)

// 1. 記錄當前挑選的心情顏色(預設金黃)
const selectedColor = ref('#E3B341')

// 2. 切換顏色的函式
function selectColor(color) {
  selectedColor.value = color
}

function addGem() {
  count.value++
  isGlowing.value = true

  setTimeout(() => {
    isGlowing.value = false
  }, 1000)
}

2. <template>:加入心情代表色與動態按鈕

在「已採集 X 顆光珠」與「放入」按鈕之間,加入四顆心情顏色圓點:

<!-- 瓶子維持原貌 -->
<div class="bottle-wrapper">
  <div class="cork"></div>
  <div class="bottle" :class="{ 'is-glowing': isGlowing }">
    <span v-if="count === 0">瓶子目前是空的</span>
  </div>
</div>

<p>已採集 {{ count }} 顆光珠</p>

<!-- 新增:心情調色盤 -->
<div class="palette">
  <button 
    class="color-dot blue" 
    :class="{ 'is-active': selectedColor === '#64B5F6' }"
    @click="selectColor('#64B5F6')"
  ></button>
  <button 
    class="color-dot gold" 
    :class="{ 'is-active': selectedColor === '#E3B341' }"
    @click="selectColor('#E3B341')"
  ></button>
  <button 
    class="color-dot pink" 
    :class="{ 'is-active': selectedColor === '#F48FB1' }"
    @click="selectColor('#F48FB1')"
  ></button>
  <button 
    class="color-dot green" 
    :class="{ 'is-active': selectedColor === '#81C784' }"
    @click="selectColor('#81C784')"
  ></button>
</div>

<!-- 採集按鈕:讓底色跟著當前選中的顏色改變,提示使用者準備放入的色調 -->
<button 
  class="btn-collect" 
  :style="{ backgroundColor: selectedColor }"
  @click="addGem"
>
  放入這道微光
</button>

3. <style scoped>:心情代表色與按鈕樣式

在底部加上心情代表色排版,以及選中時的視覺回饋:

/* 調色盤排版 */
.palette {
  display: flex;
  gap: 12px;
  margin: 12px 0 16px 0;
}

/* 心情代表色 */
.color-dot {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 2px solid transparent;
  cursor: pointer;
  transition: transform 0.2s ease, border-color 0.2s ease;
}

/* 各別顏色定義 */
.color-dot.blue { background-color: #64B5F6; }
.color-dot.gold { background-color: #E3B341; }
.color-dot.pink { background-color: #F48FB1; }
.color-dot.green { background-color: #81C784; }

/* 當前被選中的心情代表色 */
.color-dot.is-active {
  border-color: #ffffff;
  transform: scale(1.25);
}

/* 採集按鈕樣式 */
.btn-collect {
  padding: 8px 20px;
  border: none;
  border-radius: 20px;
  color: #1a1a1a;
  font-weight: bold;
  cursor: pointer;
  transition: background-color 0.3s ease, transform 0.1s ease;
}

.btn-collect:active {
  transform: scale(0.96);
}

三、成果展示

https://ithelp.ithome.com.tw/upload/images/20260922/20178067HhxWvpK6PI.png
這邊有幾點要確認:

  1. 按鈕是否有隨著選擇不同顏色的圓點而變換顏色。
  2. 按下「放入這道微光」的按鈕後,「採集 X 顆光珠」是否有跟著增加數字。
  3. 按下「放入這道微光」的按鈕後,瓶身是否有發光。

這三點都有達成的話,就能確定新增的功能和前面的舊功能都有完整呈現。
今天我們將心情調色盤設計出來了,也成功串接功能,採集瓶的功能已經做完一大部分了!

明日預告

明天(Day 9)我們將要做出「文字輸入框」,讓使用者可以將每日的小小美好以實質文字型態留下來~


上一篇
【Day 7】 元件化拆分:整理 App.vue,新建 GemJar.vue
下一篇
【Day 9】寫下今天的心情!v-model 讓輸入框記住你想說的話
系列文
微光採集瓶:用 Vue 3 打造每日美好記錄網頁 共 19 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言