本文 AI 產出,尚未審核

Vue3 教學:模板語法(Template Syntax)— 動態 style 綁定


簡介

在 Vue3 中,**樣式(style)**是 UI 呈現的核心要素之一。傳統的 CSS 靜態寫法在面對需要根據資料狀態即時變化的介面時,往往顯得力不從心。Vue 的 動態 style 綁定 讓開發者可以直接在模板中根據組件的資料或計算屬性(computed)來調整元素的外觀,實現「資料驅動」的 UI。

掌握動態 style 綁定不只可以讓程式碼更簡潔,還能提升可維護性與重用性。無論是根據使用者互動改變背景顏色、根據螢幕尺寸調整字體大小,或是實作主題切換(dark / light mode),都是日常開發中常見的需求。本篇文章將從基本語法、實作範例、常見陷阱,到最佳實踐與真實案例,完整說明 Vue3 中的動態 style 綁定。


核心概念

1. :style 簡寫與物件語法

Vue 在模板中提供 v-bind:style(簡寫為 :style)指令,用來把 JavaScript 物件 直接映射為行內樣式。物件的 key 為 CSS 屬性(使用駝峰式或字串),value 為對應的值。

<div :style="{ color: textColor, fontSize: fontSize + 'px' }">
  動態文字樣式
</div>
  • textColorfontSize 為組件內的 data 或 computed 屬性。
  • 若屬性值是 數字,Vue 會自動加上 px(但僅限於部分屬性),為了保險起見,建議手動加上單位。

2. 陣列語法(多個樣式物件合併)

有時候樣式需要根據多個來源合併,例如基礎樣式 + 狀態樣式。此時可以使用 陣列,Vue 會依序合併每個物件,後面的會覆蓋前面的同名屬性。

<div :style="[baseStyle, hoverStyle, activeStyle]">
  多層樣式合併
</div>

3. 使用計算屬性(computed)產生樣式物件

若樣式邏輯較為複雜,直接寫在模板會讓程式碼雜亂。計算屬性可以把樣式封裝起來,保持模板的可讀性。

export default {
  data() {
    return {
      isError: false,
      progress: 0
    };
  },
  computed: {
    progressBarStyle() {
      return {
        width: this.progress + '%',
        backgroundColor: this.isError ? 'red' : 'green'
      };
    }
  }
};
<div class="progress" :style="progressBarStyle"></div>

4. 動態 CSS 變數(CSS Custom Properties)

Vue 也支援 CSS 變數 的綁定,讓樣式的變化更具彈性。只要在樣式表中使用 var(--my-var),再在模板中透過 :style 設定變數即可。

<div class="card" :style="{ '--card-bg': cardBg }">
  使用 CSS 變數的卡片
</div>
.card {
  background: var(--card-bg, #fff);
  padding: 1rem;
  border-radius: 8px;
}

5. 內聯樣式 vs. class 綁定

雖然 :style 方便快速變更單一屬性,但若樣式較多或需要支援偽類(:hover、:active)時,class 綁定:class)仍是首選。本文仍以 :style 為主,並在「常見陷阱」中說明何時切換。


程式碼範例

以下示範 5 個常見且實用的動態 style 綁定情境,皆附上完整說明。

範例 1️⃣ 基本物件綁定:變色按鈕

<template>
  <button
    :style="{ backgroundColor: btnColor, color: '#fff', padding: '0.5rem 1rem' }"
    @click="toggleColor"
  >
    點我切換顏色
  </button>
</template>

<script setup>
import { ref } from 'vue'

const btnColor = ref('steelblue')
function toggleColor() {
  btnColor.value = btnColor.value === 'steelblue' ? 'tomato' : 'steelblue'
}
</script>
  • 說明btnColorref,點擊時切換顏色,樣式即時更新。

範例 2️⃣ 陣列合併樣式:卡片懸停效果

<template>
  <div
    class="card"
    :style="[baseStyle, isHover ? hoverStyle : {}]"
    @mouseenter="isHover = true"
    @mouseleave="isHover = false"
  >
    Hover 我看見變化
  </div>
</template>

<script setup>
import { ref } from 'vue'

const isHover = ref(false)

const baseStyle = {
  width: '200px',
  height: '120px',
  backgroundColor: '#f5f5f5',
  transition: 'transform 0.3s, box-shadow 0.3s'
}
const hoverStyle = {
  transform: 'translateY(-5px)',
  boxShadow: '0 8px 20px rgba(0,0,0,0.15)'
}
</script>

<style scoped>
.card {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
}
</style>
  • 說明:使用陣列把 baseStyle 與條件式 hoverStyle 合併,達成乾淨的懸停動畫。

範例 3️⃣ 計算屬性產生進度條樣式

<template>
  <div class="progress-wrapper">
    <div class="progress-bar" :style="barStyle"></div>
  </div>

  <input type="range" min="0" max="100" v-model="progress" />
</template>

<script setup>
import { ref, computed } from 'vue'

const progress = ref(45)

const barStyle = computed(() => ({
  width: `${progress.value}%`,
  backgroundColor: progress.value > 80 ? '#ff5252' : '#42b983',
  height: '100%'
}))
</script>

<style scoped>
.progress-wrapper {
  width: 100%;
  height: 20px;
  background: #e0e0e0;
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 1rem;
}
.progress-bar {
  transition: width 0.2s ease;
}
</style>
  • 說明progress 透過滑桿調整,barStyle 會即時計算寬度與顏色。

範例 4️⃣ CSS 變數結合主題切換

<template>
  <div class="theme-box" :style="{ '--bg': currentBg, '--txt': currentTxt }">
    <p>這是一段文字,會跟著主題變色。</p>
    <button @click="toggleTheme">切換主題</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const isDark = ref(false)
const currentBg = computed(() => (isDark.value ? '#333' : '#fff'))
const currentTxt = computed(() => (isDark.value ? '#eee' : '#222'))

function toggleTheme() {
  isDark.value = !isDark.value
}
</script>

<style scoped>
.theme-box {
  background: var(--bg);
  color: var(--txt);
  padding: 1.5rem;
  border-radius: 6px;
  text-align: center;
}
button {
  margin-top: 1rem;
}
</style>
  • 說明:透過 --bg--txt 兩個 CSS 變數,實作簡易的暗黑 / 亮色切換。

範例 5️⃣ 多屬性條件綁定:表單驗證提示

<template>
  <form @submit.prevent="handleSubmit">
    <input
      v-model="email"
      placeholder="請輸入 Email"
      :style="emailStyle"
    />
    <span v-if="emailError" class="error-msg">Email 格式不正確</span>

    <button type="submit">送出</button>
  </form>
</template>

<script setup>
import { ref, computed } from 'vue'

const email = ref('')
const emailError = ref(false)

const emailStyle = computed(() => ({
  border: emailError.value ? '2px solid #ff5252' : '1px solid #ccc',
  padding: '0.4rem',
  borderRadius: '4px'
}))

function handleSubmit() {
  const pattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
  emailError.value = !pattern.test(email.value)
  if (!emailError.value) {
    alert('送出成功!')
  }
}
</script>

<style scoped>
.error-msg {
  color: #ff5252;
  font-size: 0.85rem;
  margin-left: 0.5rem;
}
</style>
  • 說明:根據驗證結果動態改變 border 樣式,給使用者即時的視覺回饋。

常見陷阱與最佳實踐

陷阱 為什麼會發生 解決方案
樣式寫成字串但忘記加單位 width: 100 會被當作 100px(部分屬性)或直接失效 始終使用字串 + 單位(如 '100px')或在計算屬性中自行拼接。
:style 內直接寫函式呼叫 每次渲染都會重新建立物件,造成效能浪費 把邏輯抽到 computedmethods,返回已緩存的物件。
過度依賴行內樣式 難以維護、無法使用偽類、媒體查詢等 樣式較多時改用 :class,只保留少量動態屬性於 :style
物件鍵名使用 kebab-case 在 JavaScript 物件中必須使用字串或駝峰式,否則會觸發語法錯誤 使用駝峰式(backgroundColor)或把鍵名寫成字串('background-color')。
樣式衝突時不易除錯 多個陣列物件同時設定同一屬性,難以判斷最終值 在開發階段使用 Vue Devtools 查看最終渲染的 style,或在計算屬性內明確設定優先順序。

最佳實踐

  1. 保持樣式物件純粹:只放與 UI 直接相關的屬性,避免把業務邏輯混在一起。
  2. 使用 computed 產生樣式物件:可自動快取,減少不必要的重新渲染。
  3. 將變化大的屬性(如動畫)抽成 CSS class,搭配 :class 動態切換。
  4. 適度使用 CSS 變數:可在全局主題或多元元件間共享樣式值。
  5. 在大型專案中建立「樣式工廠」(style helper)函式,統一管理顏色、間距等設計系統變數。

實際應用場景

  1. 即時儀表板(Dashboard)
    • 根據資料變化改變圖表顏色、警示框背景、文字粗細。
  2. 暗黑模式切換
    • 透過 CSS 變數與 :style 結合,一鍵切換全站配色。
  3. 表單驗證即時回饋
    • 錯誤時把 borderbackground 改為警示色,提升使用者體驗。
  4. 漸層或動畫效果
    • 利用 :style 動態改變 backgroundImagetransform,產生互動式過場。
  5. 多語系或客製化 UI
    • 不同語系可能需要不同字體大小或行高,使用 :style 依語系自動調整。

總結

動態 style 綁定是 Vue3 提供的 資料驅動 UI 的核心能力之一。透過 :style、陣列合併、計算屬性與 CSS 變數,我們可以在模板中直接以 JavaScript 表達樣式邏輯,實現即時、可維護且彈性的介面變化。

  • 掌握基本語法:物件與陣列寫法是最常用的兩種方式。
  • 善用 computed:將複雜邏輯抽離,提升效能與可讀性。
  • 避免常見陷阱:記得加單位、避免過度行內樣式、利用 Devtools 觀察最終結果。
  • 結合 CSS 變數:讓主題切換與全局樣式管理更為簡潔。

只要熟練上述概念與最佳實踐,您就能在 Vue3 專案中靈活地控制每一個視覺細節,打造出既美觀又具互動性的使用者體驗。祝您寫程式寫得開心,介面寫得更棒!