96SEO 2026-04-20 09:58 2
我们常常陷入一种焦虑:项目越Zuo越大,文件越来越厚,改一个简单的按钮颜色似乎dou要牵一发而动全身。你是否也曾盯着屏幕上那几千行混杂着 API 调用、业务逻辑判断和 DOM 操作的 Vue 组件发呆,心里默默祈祷不要引入新的 Bug?这不仅是技术债,geng是对我们开发热情的无情消耗。今天我想和大家聊聊如何通过“整洁架构”来拯救我们的代码,让前端开发重新回归理性与优雅。

老实说前端圈子里从来不缺架构模式。从早期的 MVC 到后来的 MVVM,再到现在的组件化,我们一直在寻找那个银弹。然而Robert C. Martin 提出的“整洁架构”思想,或许Neng给我们带来不一样的视角。它的核心并不在于某种特定的框架,而在于分层与依赖规则。
想象一下你的应用是一个洋葱。Zui外层是那些容易变的东西——UI 框架、Web 框架、数据库、甚至是一些外部的第三方库。而Zui内层,则是那些Zui珍贵、Zui不容易变的业务规则和核心逻辑。整洁架构的原则hen简单:源代码依赖关系只Neng指向内部。内层完全不知道外层的存在外层通过依赖倒置来调用内层。
这听起来可Neng有点抽象,但试想一下Ru果哪天 Vue 不再流行了或者我们要把项目从 Web 端迁移到小程序端,Ru果你的业务逻辑dou死死地耦合在 Vue 组件里那简直就是一场灾难。而整洁架构告诉我们,把核心逻辑抽离出来无论外层怎么变,你的核心依然稳如泰山。
核心原则:依赖倒置与关注点分离在深入代码之前,我们必须先达成两个共识:
1. 框架是细节,业务逻辑才是核心。 不要让框架绑架了你的思维。Vue 或 React 只是工具,用来把数据渲染到屏幕上。真正的价值在于你如何处理购物车的结算、如何计算折扣、如何验证用户输入。这些规则不应该写在组件里它们应该独立存在甚至Ke以用纯 JavaScript/TypeScript 来表达。
2. 依赖倒置原则。 高层模块不应该依赖低层模块,二者dou应该依赖于抽象。在前端语境下这意味着我们的业务逻辑不应该直接依赖 Axios或者 Vue Router。相反,我们应该定义接口,让具体的实现去适配这些接口。
逐层拆解:构建坚不可摧的代码堡垒为了让大家geng直观地理解,我们以一个经典的电商购物车场景为例,来kankan如何在实际项目中落地这套架构。我们将代码划分为四个主要层次:UI 框架层、应用层、基础设施层以及Zui核心的领域层。
领域层:业务逻辑的避风港这是整个系统的灵魂所在。在这里没有 `import axios`,也没有 `import vue`,只有纯粹的 TypeScript 类和函数。这里定义了我们的实体、值对象以及聚合根。
比如我们处理金额时不Neng仅仅用一个 `number`,因为金额涉及到币种、精度计算以及合法性校验。这时候,值对象就派上用场了。
// domain/value-objects/Money.ts
export class Money {
constructor {
if throw new Error;
}
add: Money {
if throw new Error;
return new Money;
}
multiply: Money {
return new Money;
}
get value: number { return this.amount; }
toString: string { return `${this.currency} ${this.amount.toFixed}`; }
}
kan到了吗?这个 `Money` 类是自洽的。任何地方拿到它,dou不用担心金额是负数,也不用担心币种混乱。这就是领域层的魅力:它把规则封装在了对象内部,而不是散落在组件的各个角落。
再来kankan购物车里的商品项。它不仅仅是一个数据对象,它还包含了自己的行为。
// domain/entities/CartItem.ts
import { Money } from '../value-objects/Money';
export class CartItem {
constructor(
public readonly productId: string,
public readonly name: string,
private unitPrice: Money,
private quantity: number,
) {
if throw new Error;
}
get totalPrice: Money {
return this.unitPrice.multiply;
}
changeQuantity: CartItem {
return new CartItem;
}
}
而作为聚合根的 `Cart`,则负责维护购物车的一致性边界。比如它规定了购物车Zui多Neng放多少件商品,或者如何合并重复添加的商品。
// domain/aggregates/Cart.ts
import { Money } from '../value-objects/Money';
import { CartItem } from '../entities/CartItem';
export class Cart {
private items: CartItem = ;
addItem: void {
const existing = this.items.find;
if {
this.items = this.items.map(i =>
i.productId === item.productId
? i.changeQuantity
: i
);
} else {
this.items.push;
}
}
removeItem: void {
this.items = this.items.filter;
}
get total: Money {
return this.items.reduce(
=> sum.add,
new Money,
);
}
get itemCount: number {
return this.items.length;
}
canAddMore: boolean {
return this.items.length <99;
}
}
请注意,所有的业务规则——比如“Zui多99件”、“合并同类项”——dou在这里。UI 组件根本不需要知道这些细节,它只需要告诉购物车“我要加东西”就行了。
应用层:用例编排的指挥家领域层定义了“是什么”,而应用层则定义了“怎么Zuo”。这一层负责编排领域对象来完成一个具体的业务目标,比如“加入购物车”或者“结算下单”。它不包含业务规则,只是像导演一样指挥各个演员上场表演。
为了遵循依赖倒置,应用层需要通过接口来操作数据,而这些接口是在领域层定义的。
// domain/repositories/CartRepository.ts
import { Cart } from '../aggregates/Cart';
export interface CartRepository {
getCart: Promise;
save: Promise;
clear: Promise;
}
有了接口,我们就Ke以编写用例了。比如 `AddToCartUseCase`,它的逻辑非常清晰:取数据 -> 校验 -> 执行 -> 存数据。
// application/usecases/AddToCartUseCase.ts
import { Cart } from '../../domain/aggregates/Cart';
import { CartItem } from '../../domain/entities/CartItem';
import { Money } from '../../domain/value-objects/Money';
import { CartRepository } from '../../domain/repositories/CartRepository';
export class AddToCartUseCase {
constructor {}
async execute: Promise {
// 1. 获取当前状态
const cart = await this.cartRepo.getCart;
// 2. 业务规则检查
if ) {
throw new Error;
}
// 3. 构建领域对象
const item = new CartItem, qty);
// 4. 执行操作
cart.addItem;
// 5. 持久化
await this.cartRepo.save;
return cart;
}
}
这种写法让测试变得异常简单。你不需要 Mock Axios,不需要 Mount 组件,你只需要测试这个类的 `execute` 方法逻辑是否正确即可。
基础设施层:连接现实与理想的桥梁既然领域层定义了 `CartRepository` 接口,总得有人去干脏活累活吧?这就是基础设施层的职责。它负责处理 HTTP 请求、数据库操作或者 LocalStorage 读写。
这里Zui关键的一步是数据转换。API 返回的是原始的 JSON,那是“脏”数据,我们需要把它转换成纯净的领域对象。
// infrastructure/repositories/ApiCartRepository.ts
import { CartRepository } from '../../domain/repositories/CartRepository';
import { Cart } from '../../domain/aggregates/Cart';
import { CartItem } from '../../domain/entities/CartItem';
import { Money } from '../../domain/value-objects/Money';
import { cartApi } from '../api/CartApi';
export class ApiCartRepository implements CartRepository {
async getCart: Promise {
// API 返回的是原始 JSON,需要转换成领域对象
const raw = await cartApi.fetchCart;
const cart = new Cart;
for {
cart.addItem, item.qty));
}
return cart;
}
async save: Promise {
// 领域对象 → 原始 JSON,给 API
const payload = {
items: cart.items.map(i => ({
productId: i.productId,
name: i.name,
price: i.unitPrice.value,
qty: i.quantity,
})),
};
await cartApi.updateCart;
}
async clear: Promise {
await cartApi.clearCart;
}
}
kan,所有的 JSON 解析和格式化逻辑dou被关在了这个笼子里。Ru果后端改了字段名,我们只需要修改这一个文件,业务逻辑层毫发无损。
UI层:只负责貌美如花终于到了Zui外层。在 Vue 或 React 组件中,我们不再写任何 `if ` 这样的判断。组件的唯一任务就是展示状态和响应用户的点击。
我们Ke以通过一个 Composable 来连接 UI 和 Use Case。
// application/composables/useCart.ts
import { ref } from 'vue';
import { AddToCartUseCase } from '../usecases/AddToCartUseCase';
import { ApiCartRepository } from '../../infrastructure/repositories/ApiCartRepository';
const cartRepo = new ApiCartRepository;
const addToCartUseCase = new AddToCartUseCase;
export function useCart {
const cart = ref;
const loading = ref;
const error = ref;
async function addItem {
loading.value = true;
error.value = null;
try {
cart.value = await addToCartUseCase.execute;
} catch {
error.value = e.message;
} finally {
loading.value = false;
}
}
return { cart, loading, error, addItem };
}
然后在组件里我们只需要简单地调用它。
{{ product.name }}
{{ error }}
这就是我们梦寐以求的“瘦组件”。它干净、纯粹,没有任何业务逻辑的负担。Ru果有一天要把 Vue 换成 React,你只需要重写这个组件和 `useCart` 里的响应式逻辑,核心的 Use Case 和 Domain 层代码完全Ke以复用。
这样Zuo的好处:不仅仅是代码好kan你可Neng会问,搞这么复杂,值得吗?让我们来对比一下:
| 场景 | 传统Zuo法 | 整洁架构 |
|---|---|---|
| 换框架 Vue→React | 重写所有业务逻辑,甚至还要重写状态管理 | 只重写 UI 层,领域层直接复用 |
| API 字段名变了 | 改几十个组件,到处报错 | 只改 `ApiCartRepository` 的转换逻辑 |
| 加新业务规则 | 在组件里到处加 if/else,生怕漏了 | 在领域对象里加,组件无感知 |
| 单元测试 | Mock axios,mount 组件,慢如蜗牛 | 直接测 `Cart.addItem`,纯函数,快如闪电 |
当然架构不是教条,不是所有的项目dou需要如此严苛的分层。Ru果你只是写一个简单的活动页,或者一个 CRUD 的后台管理原型,引入这么多层反而会显得过度设计,增加开发成本。
但是当你的项目变得复杂,业务逻辑开始纠缠不清,或者团队规模扩大导致维护成本急剧上升时这种架构的价值就会显现出来。它就像是为你的代码穿上了一层盔甲,虽然穿起来麻烦一点,但在战场上Neng救命。
我们Ke以根据项目的实际情况,灵活地调整层级。有时候,Infrastructure 和 Application Ke以合并,或者 Domain 层Ke以简化。但无论如何,保持核心业务逻辑的纯净,始终是我们应该追求的目标。
代码是写给人kan的在这个浮躁的代码世界里我们希望Neng吸引一股把代码写好的清流。整洁架构不仅仅是一种技术方案,geng是一种对代码质量的敬畏之心。它让我们在加班的深夜里面对自己写下的代码时依然Neng保持一份从容和自信。
希望大家douNeng成为geng好的前端开发工程师,不仅仅是写出Neng运行的代码,geng是写出优雅、可维护、经得起时间考验的代码。毕竟软件工程归根结底,是为了降低复杂度,而不是为了炫技。让我们一起,构建可持续维护的现代 Web 应用吧!
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback