首页 > web前端 > js教程 > 正文

组织前端项目的组件文件夹

WBOY
发布: 2024-08-08 15:30:49
原创
732 人浏览过

Organizing the Frontend project

文件夹结构前端项目的组件非常重要。因为它使项目的开发和维护变得更加容易。特别是在处理大型或复杂的组件时,组织文件夹有助于使代码井井有条,并且更易于查找和理解

这是文件夹结构。各种格式的组件常用于使用开发的项目Next.jsTypeScript:

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)

该结构旨在支持跨平台开发。 组件驱动开发 (CDD) 使用 Storybook,它允许您以独立于主应用程序的格式开发和测试组件

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中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!