ホームページ  >  記事  >  ウェブフロントエンド  >  フロントエンド プロジェクトのコンポーネント フォルダーを整理する

フロントエンド プロジェクトのコンポーネント フォルダーを整理する

WBOY
WBOYオリジナル
2024-08-08 15:30:49734ブラウズ

Organizing the Frontend project

フォルダー構造フロントエンド プロジェクトのコンポーネントは重要です。プロジェクトの開発と維持が容易になるからです。特に大規模なコンポーネントや複雑なコンポーネントを扱う場合、フォルダーを整理するとコードが整理され、見つけやすく、理解しやすくなります。

フォルダー構造は次のとおりです。さまざまな形式の

コンポーネントを使用して開発されたプロジェクトで一般的に使用されますNext.js および TypeScript:

1.

アトミックな設計構造

アトミック デザイン は、コンポーネントをその複雑さと機能に応じて分割する設計概念です。原子、分子、生物、テンプレート、ページの 5 つのレベルに分かれています。

src/
└── components/
    ├── atoms/             # Small, reusable elements (e.g., buttons, inputs)
    │   ├── Button.tsx
    │   ├── Input.tsx
    │   ├── Icon.tsx
    │   └── ...            # Additional atoms
    │
    ├── molecules/         # Combinations of atoms (e.g., form groups)
    │   ├── FormInput.tsx
    │   ├── NavLink.tsx
    │   └── ...            # Additional molecules
    │
    ├── organisms/         # Complex UI components (e.g., headers, cards)
    │   ├── Header.tsx
    │   ├── Card.tsx
    │   ├── Footer.tsx
    │   └── ...            # Additional organisms
    │
    ├── templates/         # Page templates (layouts with placeholders)
    │   ├── MainLayout.tsx
    │   ├── DashboardLayout.tsx
    │   └── ...            # Additional templates
    │
    └── pages/             # Page-specific components (used directly in pages)
        ├── HomePage.tsx
        ├── AboutPage.tsx
        └── ...            # Additional page components
例:

アトム: Button.tsx

import React from 'react';

interface ButtonProps {
  label: string;
  onClick: () => void;
  type?: 'button' | 'submit' | 'reset';
  disabled?: boolean;
}

const Button: React.FC<ButtonProps> = ({ label, onClick, type = 'button', disabled = false }) => (
  <button type={type} onClick={onClick} disabled={disabled} className="btn">
    {label}
  </button>
);

export default Button;
分子: FormInput.tsx

import React from 'react';
import Input from '../atoms/Input';
import Label from '../atoms/Label';

interface FormInputProps {
  label: string;
  value: string;
  onChange: (value: string) => void;
}

const FormInput: React.FC<FormInputProps> = ({ label, value, onChange }) => (
  <div className="form-input">
    <Label text={label} />
    <Input value={value} onChange={onChange} />
  </div>
);

export default FormInput;
生物: Header.tsx

import React from 'react';
import NavLink from '../molecules/NavLink';
import Logo from '../atoms/Logo';

const Header: React.FC = () => (
  <header className="header">
    <Logo />
    <nav>
      <NavLink href="/" label="Home" />
      <NavLink href="/about" label="About" />
      <NavLink href="/contact" label="Contact" />
    </nav>
  </header>
);

export default Header;
2.

機能ベースの構造

機能またはモジュールごとにコンポーネントを分離する構造は、機能が豊富なプロジェクトで一般的です。機能の効率的な管理と拡張を支援します


src/
└── components/
    ├── authentication/    # Components related to authentication
    │   ├── Login.tsx
    │   ├── Signup.tsx
    │   └── PasswordReset.tsx
    │
    ├── dashboard/         # Components specific to the dashboard
    │   ├── DashboardHeader.tsx
    │   ├── DashboardSidebar.tsx
    │   └── StatsCard.tsx
    │
    ├── userProfile/       # Components for user profile
    │   ├── ProfileHeader.tsx
    │   ├── EditProfileForm.tsx
    │   └── Avatar.tsx
    │
    ├── shared/            # Shared or common components across features
    │   ├── Button.tsx
    │   ├── Modal.tsx
    │   └── ...            # Additional shared components
    │
    └── layout/            # Layout components
        ├── Header.tsx
        ├── Footer.tsx
        └── Sidebar.tsx
例:

認証: Login.tsx

import React, { useState } from 'react';
import Button from '../shared/Button';
import FormInput from '../shared/FormInput';

const Login: React.FC = () => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');

  const handleLogin = () => {
    // Logic for login
  };

  return (
    <div className="login">
      <h2>Login</h2>
      <FormInput label="Email" value={email} onChange={setEmail} />
      <FormInput label="Password" value={password} onChange={setPassword} />
      <Button label="Login" onClick={handleLogin} />
    </div>
  );
};

export default Login;
ダッシュボード: StatsCard.tsx

import React from 'react';

interface StatsCardProps {
  title: string;
  value: number;
  icon: React.ReactNode;
}

const StatsCard: React.FC<StatsCardProps> = ({ title, value, icon }) => (
  <div className="stats-card">
    <div className="stats-card-icon">{icon}</div>
    <div className="stats-card-info">
      <h3>{title}</h3>
      <p>{value}</p>
    </div>
  </div>
);

export default StatsCard;
3.

ドメイン駆動型構造

この構造は、プロジェクトのドメインまたは限定されたコンテキストに従ってコンポーネントを整理することに重点を置いています。これにより、この構造は明確なドメイン分離を必要とする複雑なシステムに適しています


src/
└── components/
    ├── domain/
    │   ├── product/       # Components related to product domain
    │   │   ├── ProductCard.tsx
    │   │   ├── ProductList.tsx
    │   │   └── ProductDetail.tsx
    │   │
    │   ├── cart/          # Components for cart domain
    │   │   ├── CartItem.tsx
    │   │   ├── CartSummary.tsx
    │   │   └── CartIcon.tsx
    │   │
    │   ├── user/          # Components for user domain
    │   │   ├── UserAvatar.tsx
    │   │   ├── UserProfile.tsx
    │   │   └── UserSettings.tsx
    │   │
    │   └── ...            # Additional domain-specific components
    │
    ├── ui/                # UI elements (atoms, molecules, etc.)
    │   ├── atoms/         
    │   ├── molecules/     
    │   └── organisms/     
    │
    └── layout/            # Layout components
        ├── Header.tsx
        ├── Footer.tsx
        └── Sidebar.tsx
例:

製品: ProductCard.tsx

import React from 'react';

interface ProductCardProps {
  name: string;
  price: number;
  imageUrl: string;
  onAddToCart: () => void;
}

const ProductCard: React.FC<ProductCardProps> = ({ name, price, imageUrl, onAddToCart }) => (
  <div className="product-card">
    <img src={imageUrl} alt={name} className="product-card-image" />
    <div className="product-card-info">
      <h3>{name}</h3>
      <p>${price.toFixed(2)}</p>
      <button onClick={onAddToCart}>Add to Cart</button>
    </div>
  </div>
);

export default ProductCard;
カート: Cartsummary.tsx

import React from 'react';

interface CartSummaryProps {
  totalItems: number;
  totalPrice: number;
}

const CartSummary: React.FC<CartSummary

Props> = ({ totalItems, totalPrice }) => (
  <div className="cart-summary">
    <h3>Cart Summary</h3>
    <p>Total Items: {totalItems}</p>
    <p>Total Price: ${totalPrice.toFixed(2)}</p>
    <button>Checkout</button>
  </div>
);

export default CartSummary;
4.

Storybook を使用したコンポーネント駆動開発 (CDD)

この構造は、クロスプラットフォーム開発をサポートするように設計されています。

Storybook を使用した コンポーネント駆動開発 (CDD)。これにより、メイン アプリケーションとは別の形式でコンポーネントを開発およびテストできます

src/
└── components/
    ├── Button/
    │   ├── Button.tsx      # Component implementation
    │   ├── Button.stories.tsx # Storybook stories
    │   ├── Button.test.tsx # Unit tests
    │   └── Button.module.css # Component-specific styles
    │
    ├── Input/
    │   ├── Input.tsx
    │   ├── Input.stories.tsx
    │   ├── Input.test.tsx
    │   └── Input.module.css
    │
    ├── Modal/
    │   ├── Modal.tsx
    │   ├── Modal.stories.tsx
    │   ├── Modal.test.tsx
    │   └── Modal.module.css
    │
    └── ...                # Additional component folders
例:

ボタン: Button.tsx

import React from 'react';
import styles from './Button.module.css';

interface ButtonProps {
  label: string;
  onClick: () => void;
  variant?: 'primary' | 'secondary';
}

const Button: React.FC<ButtonProps> = ({ label, onClick, variant = 'primary' }) => (
  <button className={`${styles.btn} ${styles[variant]}`} onClick={onClick}>
    {label}
  </button>
);

export default Button;
ボタン: Button.stories.tsx (ストーリーブック)

import React from 'react';
import { Meta, Story } from '@storybook/react';
import Button, { ButtonProps } from './Button';

export default {
  title: 'Components/Button',
  component: Button,
} as Meta;

const Template: Story<ButtonProps> = (args) => <Button {...args} />;

export const Primary = Template.bind({});
Primary.args = {
  label: 'Primary Button',
  onClick: () => console.log('Primary Button Clicked'),
  variant: 'primary',
};

export const Secondary = Template.bind({});
Secondary.args = {
  label: 'Secondary Button',
  onClick: () => console.log('Secondary Button Clicked'),
  variant: 'secondary',
};
5.

共有コンポーネント ライブラリ

複数のチームが協力して作業するプロジェクトの場合共通のコンポーネントを使用する構造を作成することが重要です。この構造は、プロジェクト全体で再利用できるコンポーネントを分離することに重点を置いています


src/
└── components/
    ├── shared/            # Shared components across the application
    │   ├── Button/
    │   │   ├── Button.tsx
    │   │   └── Button.module.css
    │   │
    │   ├── Modal/
    │   │   ├── Modal.tsx
    │   │   └── Modal.module.css
    │   │
    │   └── ...            # Additional shared components
    │
    ├── featureSpecific/   # Feature-specific components
    │   ├── UserProfile/
    │   │   ├── ProfileHeader.tsx
    │   │   ├── ProfileDetails.tsx
    │   │   └── Avatar.tsx
    │   │
    │   ├── ProductList/
    │   │   ├── ProductCard.tsx
    │   │   └── ProductFilter.tsx
    │   │
    │   └── ...            # Additional feature-specific components
    │
    └── layout/            # Layout components
        ├── Header.tsx
        ├── Footer.tsx
        └── Sidebar.tsx

ตัวอย่าง:

Shared: Modal.tsx

import React from 'react';
import styles from './Modal.module.css';

interface ModalProps {
  title: string;
  isOpen: boolean;
  onClose: () => void;
}

const Modal: React.FC<ModalProps> = ({ title, isOpen, onClose, children }) => {
  if (!isOpen) return null;

  return (
    <div className={styles.modalOverlay}>
      <div className={styles.modal}>
        <h2>{title}</h2>
        <button className={styles.closeButton} onClick={onClose}>
          &times;
        </button>
        <div className={styles.modalContent}>{children}</div>
      </div>
    </div>
  );
};

export default Modal;

Feature-Specific: ProfileHeader.tsx

import React from 'react';

interface ProfileHeaderProps {
  name: string;
  bio: string;
  avatarUrl: string;
}

const ProfileHeader: React.FC<ProfileHeaderProps> = ({ name, bio, avatarUrl }) => (
  <div className="profile-header">
    <img src={avatarUrl} alt={name} className="profile-avatar" />
    <h1>{name}</h1>
    <p>{bio}</p>
  </div>
);

export default ProfileHeader;

Factors to Consider When Structuring Components

  1. Reusability: ควรแยก component ที่สามารถใช้ซ้ำได้ออกจาก component ที่เฉพาะเจาะจงกับฟีเจอร์
  2. Maintainability: การจัดโครงสร้างที่ดีช่วยให้การดูแลรักษาและการอัพเดตโปรเจคเป็นไปอย่างราบรื่น
  3. Scalability: โครงสร้างที่ดีจะช่วยให้การขยายฟีเจอร์และการเพิ่ม component ใหม่ ๆ เป็นเรื่องง่าย
  4. Performance: ใช้เทคนิคที่เหมาะสมในการโหลดและใช้ component เพื่อให้แน่ใจว่าแอปพลิเคชันของคุณมีประสิทธิภาพ

Best Practices for Component Structure

  • Single Responsibility Principle: แต่ละ component ควรทำหน้าที่เดียวและทำได้ดี
  • Component Naming: ตั้งชื่อ component ให้สื่อความหมายและชัดเจน
  • Component Composition: ใช้ composition แทน inheritance เมื่อสร้าง component ใหม่
  • Use Prop Types or TypeScript: กำหนด prop types หรือใช้ TypeScript interfaces เพื่อเพิ่มความปลอดภัยในการใช้งาน
  • Write Tests: เขียน unit tests สำหรับ component ทุกตัวเพื่อตรวจสอบการทำงาน

ด้วยข้อมูลและแนวทางเหล่านี้ หวังว่าคุณจะสามารถจัดโครงสร้างในโฟลเดอร์ components ของโปรเจคได้อย่างมีประสิทธิภาพและเหมาะสมกับความต้องการของโปรเจคของคุณ!

以上がフロントエンド プロジェクトのコンポーネント フォルダーを整理するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
前の記事:JWT を理解する次の記事:JWT を理解する