2025-01-14 JavaScript 系列八:第4課 ── 行事曆應用程式-步驟05
我的按鈕想做成 RWD , 當變成手機的螢幕大小時,變成沒有文字的圖示按鈕
太棒了~你想讓按鈕在手機上變成圖示(icon button),這就是 RWD(響應式設計)的好實踐 👏
我來教你一步一步怎麼做,用最簡單的方法來實現這個效果!
✅ 效果目標:
- 👉 電腦螢幕:按鈕顯示「新增活動」文字
- 👉 手機螢幕:按鈕只顯示 ➕ 圖示(用 emoji 或 FontAwesome)
🧾 修改樣式(Calendar.vue 的 <style scoped> 裡)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| .add-event-button { background-color: #007bff; color: white; border: none; padding: 4px 8px; border-radius: 4px; cursor: pointer; font-size: 12px; display: inline-flex; align-items: center; gap: 4px; }
.add-event-icon { display: none; }
@media (min-width: 600px) { .add-event-text { display: inline; } }
@media (max-width: 599px) { .add-event-text { display: none; } .add-event-icon { display: inline; } }
|
🧾 修改 JS 建立按鈕的部分(dateClick 裡)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| const button = document.createElement('button') button.className = 'add-event-button'
const icon = document.createElement('span') icon.className = 'add-event-icon' icon.textContent = '➕'
const text = document.createElement('span') text.className = 'add-event-text' text.textContent = '新增活動'
button.appendChild(icon) button.appendChild(text)
|
這樣一來:
- 👀 在桌機畫面會看到:➕ 新增活動
- 📱 在手機畫面只會看到:➕
想加 FontAwesome 圖示?
只要在 index.html 加上這一行就能用:
1
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" />
|
然後把 icon.textContent = '➕' 改為:
1
| icon.innerHTML = '<i class="fas fa-plus"></i>'
|
要不要我幫你加上完整的程式碼一起貼上測試?還是你想先自己試看看?😎
很好問題!針對你使用的 Vue <style scoped>,如果你希望在 scoped 樣式中,影響由 JS 動態插入的 DOM 元素(像你用 FullCalendar 建的 .add-event-button),這時候就要用 :deep()。
✅ 所以你應該這樣寫:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| :deep(.add-event-button) { background-color: #007bff; color: white; border: none; padding: 4px 8px; border-radius: 4px; cursor: pointer; font-size: 12px; display: inline-flex; align-items: center; gap: 4px; }
:deep(.add-event-text) { display: inline; }
:deep(.add-event-icon) { display: none; }
@media (max-width: 599px) { :deep(.add-event-text) { display: none; }
:deep(.add-event-icon) { display: inline; } }
|
💡 為什麼要用 :deep()?
因為 .add-event-button 是你用 JS 動態加入到 DOM 裡的,它不是 .vue 組件內部產生的元素,因此 scoped CSS 的 attribute selector 不會套用到它。
使用 :deep() 就能讓 CSS 穿透 scoped 限制,正確影響這些外部或第三方 DOM。
小提醒:
:deep() 只需要加在 .vue 檔的 scoped <style> 中
- 如果你改成
<style> 沒有 scoped,就不需要 :deep(),但會全域影響整個網站樣式
你要不要我幫你整理成完整的 RWD calendar 按鈕小樣板?還是你想自己組合試試?😄
當然可以,這裡是整理後的版本,包含以下幾個重點:
✅ 使用 :deep() 讓按鈕樣式正確套用
✅ 按鈕插入 .fc-daygrid-day-frame 中,保持版面整潔
✅ 保留點擊事件,可以擴充成開啟表單功能
✅ 結構清楚,註解清晰,方便日後維護
✅ 整理後的程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| <template> <div> <h2>我的行事曆</h2> <div ref="calendarRef" id="calendar"></div> </div> </template>
<script setup> import { ref, onMounted } from 'vue'
const calendarRef = ref(null)
onMounted(() => { if (window.FullCalendar && window.FullCalendar.Calendar) { const calendar = new window.FullCalendar.Calendar(calendarRef.value, { initialView: 'dayGridMonth', locale: 'zh-tw', events: [ { title: '測試活動', start: new Date().toISOString().split('T')[0], // 今天 } ], dateClick(info) { // 🧪 印出 DOM 結構可供除錯觀察 console.log(info.dayEl.outerHTML)
// 移除已存在的新增按鈕 document.querySelectorAll('.add-event-button').forEach(btn => btn.remove())
// ✅ 找到可插入的區塊(不是 dayEl 自己,避免 layout 混亂) const cellEl = info.dayEl.querySelector('.fc-daygrid-day-frame') if (!cellEl) return
// 建立按鈕元素 const button = document.createElement('button') button.textContent = '新增活動' button.className = 'add-event-button'
// 設定點擊行為 button.onclick = () => { alert(`你點了 ${info.dateStr},這裡可以打開活動編輯表單!`) }
// 插入到 cell 中 cellEl.appendChild(button) } }) calendar.render() } else { console.error('FullCalendar 尚未載入,請檢查 index.html CDN script。') } }) </script>
<style scoped> #calendar { max-width: 800px; margin: 20px auto; }
/* ✅ 使用 :deep() 讓樣式能穿透 scoped 套用到 JS 動態加的按鈕 */ :deep(.add-event-button) { background-color: #1e2b37; color: white; border: none; padding: 2px 6px; border-radius: 4px; cursor: pointer; font-size: 12px; } </style>
|
如果你要進一步做 RWD 的圖示按鈕切換(例如手機只顯示 icon),我可以再幫你加入 @media 和 icon 的樣式結構 👌
要不要我幫你做那一段也一起整進來?
太好了,我幫你把 RWD 版本整合進來了 ✅
目標是:
- 電腦寬度下顯示「新增活動」文字按鈕
- 手機寬度下變成只顯示 icon(使用 emoji 作為示意,可換成 Font Awesome 等)
✅ 完整整合版:含 :deep() + RWD 響應式樣式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| <template> <div> <h2>我的行事曆</h2> <div ref="calendarRef" id="calendar"></div> </div> </template>
<script setup> import { ref, onMounted } from 'vue'
const calendarRef = ref(null)
onMounted(() => { if (window.FullCalendar && window.FullCalendar.Calendar) { const calendar = new window.FullCalendar.Calendar(calendarRef.value, { initialView: 'dayGridMonth', locale: 'zh-tw', events: [ { title: '測試活動', start: new Date().toISOString().split('T')[0], } ], dateClick(info) { console.log(info.dayEl.outerHTML)
// 移除舊按鈕 document.querySelectorAll('.add-event-button').forEach(btn => btn.remove())
const cellEl = info.dayEl.querySelector('.fc-daygrid-day-frame') if (!cellEl) return
// 建立按鈕 const button = document.createElement('button') button.className = 'add-event-button' button.innerHTML = `<span class="text">新增活動</span><span class="icon">➕</span>` // icon 可改用 Font Awesome
button.onclick = () => { alert(`你點了 ${info.dateStr},這裡可以打開活動編輯表單!`) }
cellEl.appendChild(button) } }) calendar.render() } else { console.error('FullCalendar 尚未載入,請檢查 index.html CDN script。') } }) </script>
<style scoped> #calendar { max-width: 800px; margin: 20px auto; }
/* ✅ 基本樣式:使用 :deep() 讓 scoped CSS 有效 */ :deep(.add-event-button) { background-color: #1e2b37; color: white; border: none; padding: 4px 8px; border-radius: 4px; cursor: pointer; font-size: 12px; display: flex; align-items: center; gap: 4px; }
/* ✅ 預設顯示文字與 icon */ :deep(.add-event-button .icon) { display: none; }
:deep(.add-event-button .text) { display: inline; }
/* ✅ 手機寬度下改為只顯示 icon */ @media (max-width: 600px) { :deep(.add-event-button .text) { display: none; } :deep(.add-event-button .icon) { display: inline; font-size: 16px; } } </style>
|
🔍 測試方式建議:
- 開啟開發者工具 → 切換手機預覽模式看看是否成功切換
- 若有安裝 icon 套件(如 Font Awesome),可將
➕ 改為 <i class="fas fa-plus"></i> 等
想進一步加 popup 表單編輯活動,或改用 modal?我也可以幫你整合進來喔!要嗎?😎