iT邦幫忙

2024 iThome 鐵人賽

DAY 19
0
JavaScript

從PM到前端開發:我的React作品集之旅系列 第 19

Day19: 動態生成 Card 元件,建構 Service 頁面

  • 分享至 

  • xImage
  •  

在過去的幾篇文章中,我們探討了 Hero Section 的設計和優化,包括使用 SVG 和動態控制來增強頁面交互效果。今天,我們將進一步完成個人網站的服務展示部分,深入討論如何動態生成一個 Card 元件,並通過 React 結合動態數據來實現卡片的展示。這篇文章將專注於如何通過動態數據驅動來靈活展示卡片內容,確保網站在不同裝置上具備高效的響應式設計。

Card 元件設計原則

Card 元件 是展示服務或產品的關鍵介面元素,尤其在響應式網頁中常見。為了提升靈活性和可擴展性,我們採用了 動態數據驅動 的設計方法,使得卡片內容能根據需求動態更新和調整。以下是我們的 Card 元件設計的核心原則:

  1. 一致性:卡片結構應統一,不論是垂直、橫向或其他佈局,應包含以下要素,方便用戶迅速理解每張卡片的重點內容:
    • 服務圖標
    • 服務標題
    • 簡短描述
    • 相關技術或工具
  2. 靈活佈局與動態數據:確保卡片對所有使用者(包括殘障人士)友好。為圖片和圖標提供替代文字,並支持鍵盤導航,提升無障礙體驗。
  3. 可訪問性:確保卡片對所有使用者(包括殘障人士)友好。為圖片和圖標提供替代文字,並支持鍵盤導航,提升無障礙體驗。

https://ithelp.ithome.com.tw/upload/images/20240918/20168330BhwsSNfRl2.png

Card 元件屬性表

我們的 Card 元件將具備以下屬性,這些屬性來自動態數據,並可以靈活地控制每張卡片的內容:

屬性 說明 類型 預設值
icon 卡片頂部的圖標 string ''
title 卡片的標題 string ''
description 卡片的描述 string ''
category 卡片底部的類別 string ''
details 卡片的詳細資訊(技術或工具) string ''
borderSVG 自定義邊框(可選的 SVG 邊框) node null

這些屬性讓我們的 Card 元件 可以靈活展示不同服務的內容,包括服務名稱、描述、技術細節

實際演練

Step 1: 更新的 i18n 配置

首先,我們將卡片數據放入 i18nresources 中,這樣我們就可以根據語言環境來動態獲取對應的卡片內容。

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import config from '@/utils/config';
import { logLevel } from '@/utils/log';

i18n.use(initReactI18next).init({
    resources: {
        en: {
            translation: {
                // .. 其他翻譯
               cardsData: [
                    {
                        icon: "React.png",
                        title: "Frontend Developer",
                        description: "Building engaging, responsive websites that transform ideas into seamless user experiences.",
                        category: "Languages",
                        details: "JavaScript (ES6+), TypeScript, HTML, CSS, Sass"
                    },
                    {
                        icon: "Figma.png",
                        title: "UI/UX Designer",
                        description: "Crafting user-centered designs balancing aesthetics and functionality for optimal usability.",
                        category: "Tools",
                        details: "Figma, Photoshop, Prototyping"
                    },
                    {
                        icon: "Training.png",
                        title: "Mentor",
                        description: "Guiding developers and designers with practical insights and real-world project experience.",
                        category: "Specializations",
                        details: "Code Reviews, Problem-Solving, Career Guidance"
                    }
                ]
            }
        },
        zh: {
            translation: {
	              // .. 其他翻譯
                cardsData: [
                    {
                        icon: "React.png",
                        title: "前端開發者",
                        description: "構建引人入勝的響應式網站,將想法轉化為無縫的用戶體驗。",
                        category: "語言",
                        details: "JavaScript (ES6+), TypeScript, HTML, CSS, Sass"
                    },
                    {
                        icon: "Figma.png",
                        title: "UI/UX 設計師",
                        description: "創造以用戶為中心的設計,平衡美觀與功能性,實現最佳可用性。",
                        category: "工具",
                        details: "Figma, Photoshop, Prototyping"
                    },
                    {
                        icon: "Training.png",
                        title: "導師",
                        description: "為開發者和設計師提供實用的建議和實際項目經驗。",
                        category: "專業",
                        details: "代碼審查、問題解決、職業指導"
                    }
                ]
            }
        },
    },
		//...其他設定
});

Step 2: Card 元件實作

接著,我們來實作一個 Card 元件,這個元件會根據傳入的動態數據來渲染。

import React from 'react';
import PropTypes from 'prop-types';
import * as styles from '@/components/cards/Card.module.scss';

const Card = ({ icon, title, description, category, details }) => {
    return (
        <div className={styles.card}>
            <div className={styles.cardHeader}>
                <img src={icon} alt={`${title} icon`} className={styles.cardIcon} />
            </div>
            <div className={styles.cardBody}>
                <h3 className={styles.cardTitle}>{title}</h3>
                <p className={styles.cardDescription}>{description}</p>
            </div>
            <div className={styles.cardFooter}>
                <p className={styles.cardCategory}>{category}</p>
                <p className={styles.cardDetails}>{details}</p>
            </div>
        </div>
    );
};

Card.propTypes = {
    children: PropTypes.string,
    title: PropTypes.string,
    description: PropTypes.string,
    category: PropTypes.string,
    details: PropTypes.string,
};

export default Card;

Step 3: ServiceSection 元件實作

在這一步,我們將實作 ServiceSection,這個元件的主要功能是渲染多個 Card 元件 並顯示於服務區塊。它會從 i18n 中動態獲取不同語言下的卡片數據,並將數據通過 Card 元件顯示出來。此外,還可以為此區塊設置一個 id,以便稍後的平滑滾動功能。

// src/components/ServiceSection/ServiceSection.jsx
import React from 'react';
import { useTranslation } from 'react-i18next';
import Card from '@/components/cards/Card';
import * as styles from '@/pages/Portfolio/ServiceSection.module.scss';

const ServiceSection = () => {
    const { t } = useTranslation();
    const services = t('cardsData', { returnObjects: true });  // 獲取服務數據

    return (
        <div id="services" className={styles.serviceSection}>
            <h2 className={styles.title}>Services we’re providing
                that derive 99% result</h2>
            <div className={styles.services}>
                {services.map((service, index) => (
                    <Card
                        key={index}
                        icon={require(`@/assets/icons/${service.icon}`)}
                        title={service.title}
                        description={service.description}
                        category={service.category}
                        details={service.details}
                    />
                ))}
            </div>
        </div>
    );
};

export default ServiceSection;

說明:

  1. 多語言支持:透過 useTranslation 函數動態獲取 cardsData,能讓頁面根據不同語言環境動態展示卡片內容。
  2. 卡片渲染:我們透過 map() 方法迭代 cardsData 數據,並使用 Card 元件來渲染每張卡片。
  3. 自定義邊框:每個卡片都可以通過 borderSVG 傳入不同的邊框樣式,增強視覺效果。

Step 4: 在 Portfolio 頁面中引用 ServiceSection

最後,我們將 ServiceSection 元件嵌入到整個 Portfolio 頁面中,這個頁面包含多個區塊(如 HeroSection 和 StatsSection)。我們將統一管理這些區塊的 id,以便未來能夠實現頁面間的平滑滾動。

// src/pages/Portfolio/Portfolio.jsx
import React from 'react';
import HeroSection from '@/components/HeroSection/HeroSection';  
import StatsSection from '@/components/Cards/StatsSection';  
import ServiceSection from '@/components/ServiceSection/ServiceSection';  // 引入ServiceSection
import styles from './Portfolio.module.scss';

const Portfolio = () => {
    return (
        <>
            <HeroSection />
            <StatsSection />
            <ServiceSection />  {/* 使用ServiceSection */}
        </>
    );
};

export default Portfolio;

說明:

  1. 區塊管理:透過 id 來統一管理頁面中各個區塊(如 HeroSectionServiceSection),未來可用於實現平滑滾動功能。
  2. 模組化設計:每個區塊(元件)都是獨立的,這樣我們可以靈活地調整頁面內容,而不需要大規模修改頁面結構。

結語

在這篇文章中,我們展示了如何使用動態數據生成響應式的 Card 元件,並通過 i18n 來支持多語言數據管理。這樣的結構讓網站內容靈活且易於維護。同時,我們遵循了 Mobile First 的設計思路,確保卡片在各種裝置上都能完美顯示。

在下一篇文章中,我們將深入探討 Grid Layout 的使用方式,並展示如何使用 CSS Grid 來實現卡片的響應式佈局。如果你對前端的數據管理和部署感興趣,請繼續關注我們的後續文章!


流光館Luma<∕> ✨ 期待與你繼續探索更多技術知識!



上一篇
Day18: 響應式設計指南,Mobile First 與 Tooltip 優化
下一篇
Day 20: CSS Grid 實戰,打造彈性卡片佈局
系列文
從PM到前端開發:我的React作品集之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言