How Clean Architecture and Vue 3 Composition API Simplify Complex Frontend Projects

This article examines the growing complexity of a points‑mall front‑end, identifies architectural and code‑organization pain points, and demonstrates how applying Clean Architecture together with Vue 3's Composition API can decouple business logic from UI, improve maintainability, and streamline development.

MoonWebTeam
MoonWebTeam
MoonWebTeam
How Clean Architecture and Vue 3 Composition API Simplify Complex Frontend Projects

1. Introduction

As front‑end business complexity increases, code‑maintenance cost, scalability, and team‑collaboration efficiency become critical issues. Studies show developers spend about 80% of their time understanding code rather than writing it. Two main dimensions cause this: uncontrolled architecture (tight coupling between business logic and framework) and limited code‑organization patterns (fragmented logic, deep nesting, bloated components).

2. Points Mall Project Background and Requirements

2.1 Project Background

The Application Bao points mall is a non‑typical e‑commerce front‑end that handles user assets, product display, and point‑based redemption. Core functions include:

User asset display – view point balance, composition, and acquisition records.

Product display – list product name, price, stock, pre‑exchange conditions, and associated games.

Point redemption – users exchange points for products.

Different product types involve distinct interaction logic, such as physical goods requiring shipping address, game items needing server selection, Q‑coin requiring QQ number, WeChat discount linked to WeChat, and coupons showing usable games.

2.2 Product Architecture Evolution

During requirement iterations, the product architecture evolved from single‑product to single‑SKU, then to SPU where an SPU can associate multiple SKUs displayed in a popup.

Dimension

SPU (Standard Product Unit)

SKU (Stock Keeping Unit)

Definition

A set of products sharing the same attributes (brand, model, core function).

A sellable physical item with a unique specification (color, storage, etc.).

Purpose

Product classification, standardized display, aggregation analysis.

Inventory management, sales tracking, order fulfillment.

Granularity

Coarse – describes a product series.

Fine – describes the smallest sellable unit.

Example

iPhone 16 (represents the whole series).

iPhone 16 Pro 512GB Titanium (unique stock identifier).

2.3 Project Pain Points

Developers often place data requests and logic directly in components. With frequent product‑architecture changes and new product types, components become bloated and nested, making code comprehension difficult and exposing maintainability and extensibility issues. When the architecture shifted from single‑SKU to SPU, the data flow and code organization required a thorough refactor.

3. Stripping the Framework: Clean Architecture

3.1 Clean Architecture

MoonWebTeam promotes applying Clean Architecture (proposed by Robert C. Martin) to front‑end development. It centers on a domain model and achieves framework‑independence through layered decoupling:

Domain Layer – pure business entities and rules (e.g., order calculation, inventory logic).

Application Layer – orchestrates domain capabilities (e.g., user order flow).

Adapter Layer – bridges UI, API, and external services.

Framework Layer – concrete Vue/React integration.

Dependency rule: outer layers may depend on inner layers, but inner layers must not depend on outer layers.

3.2 Group Layer Implementation Survey

Our investigation found most code does not follow strict inner‑to‑outer one‑way dependencies; instead, it leans toward DDD practices.

DDD

Clean Architecture

Layering Logic

Divided by business domain (user, order, etc.)

Divided by technical responsibility (entity → use‑case → adapter → framework)

Dependency Direction

Cross‑layer calls allowed

Strict one‑way (inner layers unaware of outer)

Relation to Framework

Not forced to decouple

Core logic must be framework‑agnostic

Typical Components

Aggregate roots, domain events, anti‑corruption layer

Use‑case controller, adapter, DI container

Common violations include:

Updating store data directly in entity or use‑case layers to trigger UI updates – this couples core logic to Vue’s reactivity.

Calling adapter methods from the entity layer to update entity properties – adapters should remain outside the domain.

Mixing UI view logic with business logic – breaks separation of concerns.

3.3 Current State of the Points Mall

The redemption logic is tightly coupled with UI: each product’s exchange flow updates UI components, triggers pop‑ups, and handles errors, leading to:

Difficult code reading – logic scattered across many files.

Code bloat – each product maintains its own specific logic, causing duplication.

High complexity – tangled data flow and deep call chains.

3.4 Clean‑Architecture Practice for the Points Mall

Key solutions:

Extract UI dialogs (exchange, result) from the use‑case; the use‑case only handles data flow.

Let view components consume the data emitted by the use‑case and trigger UI actions (open/close dialogs, error handling).

3.4.1 Extract Domain Entities and Use‑Cases

Domain Entities (Domain Layer) – Product entities (SPU, SKU) are defined as TypeScript types.

// Domain entities (Domain Layer)
// User entity
class User {
  private balance: number;
  private consumptionRecords: ConsumptionRecord[];
}

// Product entity
class Product {
  id: string;
  stock: number;
  checkStock(): boolean { return this.stock > 0; }
  applyLimitRule(): boolean { return true; }
}

Use‑Case (Application Layer)

class ExchangeUseCase {
  constructor(private exchangeService: ExchangeService) {}
  async execute(user: User, product: Product): Promise<Order> {
    if (!product.checkStock()) throw new Error('库存不足');
    user.deductPoints(product.pointsRequired);
    return this.exchangeService.createOrder(user, product);
  }
}

3.4.2 Composition API Integration

Using Vue 3 hooks to implement the layered architecture:

// useExchange.ts – composable business logic
export const useExchange = (product: Ref<Product>, user: Ref<User>) => {
  const orderStore = useOrderStore();
  const error = ref<Error | null>(null);

  const executeExchange = async () => {
    try {
      const exchangeService = inject(ExchangeServiceKey);
      await exchangeService.deductPoints(user.value, product.value.points);
      orderStore.orderResult = await exchangeService.createOrder(product.value);
    } catch (err) {
      error.value = err as Error;
    }
  };

  const showConfirmDialog = () => {
    Modal.confirm({ title: '确认兑换?', content: product.value.name });
  };

  return { executeExchange, showConfirmDialog, orderResult: orderStore.orderResult, error };
};

The composable maps to Clean Architecture layers: useExchange lives in the UI/Hooks layer, orchestrates domain entities and use‑cases, while adapters handle API‑to‑entity conversion.

3.5 Comparative Advantages

Dimension

Traditional Layered Architecture

Reactive Clean Architecture

Data Flow

Strict one‑way

Reactive closed‑loop

State Management

Prop drilling across layers

Reactive context sharing

Code Reuse

Inheritance / composition patterns

Hooks composition

Framework Coupling

Fully decoupled

Selective coupling via hooks

Development Efficiency

High cognitive cost

Matches front‑end intuition

Typical Code Size

5‑layer structure

3‑layer reactive

5. Conclusion

Front‑end architecture balances determinism and flexibility. Vue 3 Composition API enables a responsive, layered approach that aligns with developers’ mental models while preserving the benefits of Clean Architecture—clear separation, easier maintenance, and better reusability. Applying these practices to the points‑mall project demonstrates how complex business requirements can be managed effectively and provides a reusable blueprint for other front‑end systems.

Clean Architecturesoftware designComposition API
MoonWebTeam
Written by

MoonWebTeam

Official account of MoonWebTeam. All members are former front‑end engineers from Tencent, and the account shares valuable team tech insights, reflections, and other information.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.