iT邦幫忙

2025 iThome 鐵人賽

DAY 7
0
Vue.js

新手學習Vue.js與實作之旅系列 第 7

Day7 Composition API 入門 + 實作簡易計數器

  • 分享至 

  • xImage
  •  

前幾天的內容都是使用Options API來撰寫範例程式碼,今天將更深入探討Composition API,並且透過實作簡易計數器來比較兩種寫法~

setup函數

<script setup> 是 Composition API 的語法糖,在撰寫Composition API會使用到,可以讓程式碼更簡潔。

ref和reactive的使用

在官方文件介紹Composition API 中,推薦使用ref() 函數來宣告響應式狀態,可以接受任何型態的資料,在<script> 中需要透過 .value 來取得資料,不過在<template>標籤內不需要寫入.value,而reactive 只能接受特定的值(物件或陣列),否則Vue 會回傳一個警告訊息,並且不需要透過 .value 來取得資料。

接下來要實作簡易計數器比較Options API 、Composition API兩種寫法,藉此可以複習先前提到的單一檔案元件(SFC)的概念,在同一檔案中透過<script>來控制元件邏輯、<template>撰寫html語法、<style>撰寫CSS美化。
P.S.以下寫法是透過Day2 建置Vue.js開發環境 介紹的方法二 (安裝Node.js和npm)來撰寫Vue

首先是使用Options API

<script>
  export default {
  data() {
    return {
      count: 0
    }
  }
}
</script>

<template>
  <main>
    <div class="container">
      <h4>Counter</h4>
      <h1 id="count">{{ count }}</h1>
      <button id="subtract" v-on:click="count--">-</button>
      <button id="add" v-on:click="count++">+</button>
    </div>
  </main>
</template>

接著是使用Composition API

<script setup>
  import {ref} from "vue";
  const count = ref(0);
</script>

<template>
  <main>
    <div class="container">
      <h4>Counter</h4>
      <h1 id="count">{{ count }}</h1>
      <button id="subtract" v-on:click="count--">-</button>
      <button id="add" v-on:click="count++">+</button>
    </div>
  </main>
</template>

比較寫法

可以發現到兩者寫法<template>標籤內的內容皆相同,其中 v-on : click="" 可以簡化寫成 
@click="",引號內寫入的不是字串,而是JavaScript表達式,只有<script>標籤內有所不同。

  • Options API
    使用 data() 函數返回物件,需要使用 export default 和完整的元件物件結構。
  • Composition API
    使用 ref() 創建響應式資料,透過使用 <script setup> 語法糖讓程式碼更簡潔。

畫面呈現結果:
https://ithelp.ithome.com.tw/upload/images/20250911/20169120TFt2qtTjNc.png

最後是CSS美化的完整程式碼

<style scoped> 代表標籤內的樣式只會應用在此文件(App.vue)中,並不會影響到其他vue檔案中的html元素。

<style scoped>
  main{

    font-family: "Segoe UI", sans-serif;
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
    margin: 0;
    background: linear-gradient(135deg, #78c299 0%, #7fcbc0 100%);
  }
        
  .container {
    background: white;
    padding: 3rem;
    border-radius: 20px;
    box-shadow: 0 20px 40px rgba(0,0,0,0.1);
    text-align: center;
    min-width: 300px;
  }
        
  h4 {
    color: #666;
    margin-bottom: 1rem;
    font-weight: bold;
    font-size: 1.2rem;
  }
        
  #count {
    font-size: 4rem;
    font-weight: bold;
    margin: 1rem 0;
    color: #333;
  }
        
  button {
    font-size: 2rem;
    width: 60px;
    height: 60px;
    border: none;
    border-radius: 50%;
    margin: 0 1rem;
    cursor: pointer;
    transition: all 0.2s ease;
    font-weight: bold;
  }
        
  #subtract {
    background:#ff6b6b;
    color: white;
  }
        
  #add {
    background:#51cf66;
    color: white;
  }
  button:hover {
    transform: translateY(-2px);
  }
  button:active {
    transform: translateY(0);
    opacity: 0.7;
  }
</style>

畫面呈現結果:
https://ithelp.ithome.com.tw/upload/images/20250911/201691205RjmJIM2bj.png

參考資源

https://vuejs.org/api/composition-api-setup.html
https://zh-hk.vuejs.org/guide/essentials/reactivity-fundamentals
https://israynotarray.com/vue/20240106/910015012/
https://www.runoob.com/vue3/vue3-composition-api.html
https://medium.com/i-am-mike/vue-3-ref-%E8%B7%9F-reactive-%E6%88%91%E8%A9%B2%E6%80%8E%E9%BA%BC%E9%81%B8-2fb6b6735a3c
https://www.youtube.com/watch?v=I_xLMmNeLDY


上一篇
Day6 Vue指令- 事件處理與修飾符
系列文
新手學習Vue.js與實作之旅7
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言