在 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」這類有外部效果的事情。
使用生命週期點時要先思考各自的優點,和有沒有更簡化的方法,今天就記錄到這!