在 Projects 區塊中,每個專案都會以卡片形式展示。隨著專案數量逐漸增加,若全部一口氣呈現,區塊會過於冗長,影響閱讀體驗。為了避免這種狀況,設計上加入了展開/收合按鈕,用來控制顯示的卡片數量,讓頁面維持簡潔,保留使用者探索的彈性。
預期的操作效果是:初始僅顯示 2-3 個卡片&View More 按鈕,點擊後展開所有卡片 & View Less 按鈕,再次點擊按鈕後,縮回顯示 2-3個卡片。
// projects/projects.vue
<template>
    <div class="px-md-12 px-lg-16 px-7 py-16 bg-light-yellow">
        <div class="text-brown text-h3-semi-bold mb-3 text-center">
            Projects
        </div>
        <div class="mt-5 text-brown"
            :class="isDesktop ? 'text-h5-regular custom-padding': 'text-h6-regular'">
            大學時期參與許多社團事務,包括彰師小生物、彰師大升學輔導種子計畫以及彰師大諮輔志工團。 其中「彰師小生物」是提供學生課程評價搜尋的服務,目前收錄1000則以上的評價回饋。我主要負責粉絲專頁的文案平面設計,以及網站平台前端網頁的建置與維護,目前粉專有1300的追蹤人數,平台有6500以上的使用者,也藉此累積了很多作品及經驗。
        </div>
        <div v-for="(project, index) in visibleProjects" :key="index">
            <ProjectCard :project="project"></ProjectCard>
        </div>
				
	    // toggle
        <div
          class="text-brown text-center text-decoration-underline"
          :class="isDesktop ? 'text-h4-semi-bold mt-10' : 'text-h5-semi-bold mt-6'"
          @click="toggleExpand"
        >
          {{ expand ? 'View Less' : 'View More' }}
      </div>
    </div>
</template>
<script setup>
import { ref } from 'vue';
import useInnerWidth from '~/composables/useInnerWidth';
import ProjectCard from './project-card.vue';
const { isDesktop } = useInnerWidth();
const projects = ref([
  {
    title: 'title',
    skills: ['skill1', 'skill2', 'skill3'],
    designConcept: 'url',
    productUrl: 'url',
  },
  ...
]);
const expand = ref(false);
// 展開時要顯示全部卡片,收合時僅顯示2個
const visibleProjects = computed(() =>
  expand.value ? projects.value : projects.value.slice(0, 2)
);
const toggleExpand = () => {
  expand.value = !expand.value;
}
</script>
自動依賴追蹤的函式
visibleProjects 依賴 expand.value 和 projects.value。visibleProjects 會自動重新計算。模板更乾淨
在 <template> 裡只需要寫 v-for="project in visibleProjects",
而不用在模板裡加 expand ? projects : projects.slice(0, 2) 這種判斷式,維護起來更直觀。
效能優化
computed 有快取(cache),只要依賴的值沒變,就不會重新計算。computed 更省資源。watch → 是用來「觸發副作用」,像是「資料變了就打 API、console log、寫入 localStorage」這類有外部效果的事情。
使用生命週期點時要先思考各自的優點,和有沒有更簡化的方法,今天就記錄到這!