mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4mobile wallpaper 5mobile wallpaper 6
1483 字
4 分钟
Vue3 前端架构重构实践
2026-04-02

Vue3 前端架构重构实践:从双端分离到统一响应式组件#

概述#

本文将详细介绍一个基于 Vue3 + TypeScript 的前端项目重构过程。通过一系列系统性的重构,我将原本分离的双端代码整合为统一的响应式组件,大幅提升了代码可维护性和开发效率。

重构背景#

在重构之前,项目采用传统的双端分离架构:

  • 桌面端组件:Home.vue、Device.vue、Data.vue 等
  • 移动端组件:MobileHome.vue、MobileDevice.vue、MobileData.vue 等

这种架构存在以下问题:

  1. 代码重复:相同功能需要在两个组件中分别实现
  2. 维护困难:修复bug或添加功能需要修改多处代码
  3. 一致性差:双端界面风格和行为难以保持一致
  4. 开发效率低:新功能开发需要编写两套代码

重构阶段详解#

阶段一:统一API层重构#

主要变更

  • 创建统一API层 src/utils/api.ts
  • 封装请求/响应拦截器
  • 替换所有组件中的 fetch 调用为 api.ts 方法
  • 实现统一错误处理和token刷新逻辑

技术实现

src/utils/api.ts
import { ElMessage } from
'element-plus';
import router from '@/router';
const BASE_URL = '';
// 请求拦截器
const requestInterceptor = (config:
RequestInit) => {
const token = localStorage.getItem
('accessToken');
const headers = new Headers(config.
headers);
if (token) {
headers.set('Authorization',
`Bearer ${token}`);
}
headers.set('Accept', 'application/
json');
return { ...config, headers,
credentials: 'include' as
RequestCredentials };
};
// 响应拦截器
const responseInterceptor = async
(response: Response) => {
if (response.status === 401) {
// 处理401错误
localStorage.removeItem
('accessToken');
localStorage.removeItem
('refreshToken');
localStorage.removeItem
('isAuthenticated');
localStorage.removeItem('username');
localStorage.removeItem('role');
window.dispatchEvent(new Event
('loginStatusChanged'));
ElMessage.error('登录已过期,请重新登
');
router.push('/Login');
throw new Error('Unauthorized');
}
if (!response.ok) {
const error = await response.json().
catch(() => ({}));
throw new Error(error.detail ||
error.msg || '请求失败');
}
return response.json();
};
// 统一请求方法
export const api = {
async get<T = any>(url: string,
params?: Record<string, any>):
Promise<T> {
let fullUrl = BASE_URL + url;
if (params) {
const searchParams = new
URLSearchParams();
Object.entries(params).forEach
(([key, value]) => {
if (value !== undefined &&
value !== null) {
searchParams.append(key,
String(value));
}
});
fullUrl += `?${searchParams.
toString()}`;
}
const config = requestInterceptor({
method: 'GET' });
const response = await fetch
(fullUrl, config);
return responseInterceptor
(response);
},
async post<T = any>(url: string, data?
: any, options?: { headers?:
Record<string, string> }): Promise<T>
{
const headers: Record<string,
string> = options?.headers || {
'Content-Type': 'application/
json' };
const config = requestInterceptor({
method: 'POST',
headers,
body: data ? (headers
['Content-Type'] === 'application/
json' ? JSON.stringify(data) :
data) : undefined
});
const response = await fetch
(BASE_URL + url, config);
return responseInterceptor
(response);
},
async put<T = any>(url: string, data?
: any): Promise<T> {
const config = requestInterceptor({
method: 'PUT',
headers: { 'Content-Type':
'application/json' },
body: data ? JSON.stringify(data)
: undefined
});
const response = await fetch
(BASE_URL + url, config);
return responseInterceptor
(response);
},
async delete<T = any>(url: string):
Promise<T> {
const config = requestInterceptor({
method: 'DELETE' });
const response = await fetch
(BASE_URL + url, config);
return responseInterceptor
(response);
}
};

优化效果

  • 14个文件被修改,代码量减少约850行
  • 统一了所有API调用的错误处理逻辑
  • 实现了自动token刷新和登录状态管理
  • 消除了重复的网络请求代码

阶段二:整合双端总览组件(Commit: c98cec87)#

主要变更

  • 整合 Home.vue 和 MobileHome.vue 为单一组件 HomePage.vue
  • 清理无用文件:FullscreenMode.vue、Old_Home.vue
  • 优化文件结构

技术实现要点

<template>
<div :class="['home-container', {
'mobile': isMobile }]">
<!-- 根据设备类型渲染不同布局 -->
<div v-if="!isMobile"
class="desktop-layout">
<!-- 桌面端布局 -->
</div>
<div v-else class="mobile-layout">
<!-- 移动端布局 -->
</div>
</div>
</template>
<script setup>
import { computed } from 'vue';
const isMobile = computed(() => {
return window.innerWidth < 768 || /
Android|webOS|iPhone|iPad|iPod|
BlackBerry|IEMobile|Opera Mini/i.test
(navigator.userAgent);
});
</script>

关键优化

  • 文件数量从6个减少到5个
  • 代码量减少约1274行
  • 实现了真正的响应式布局

阶段三:整合双端设备界面组件(Commit: 94572906)#

主要变更

  • 创建统一的 DevicePage.vue 组件
  • 删除 Device.vue 和 MobileDevice.vue
  • 更新路由配置

技术挑战: 设备管理界面功能复杂,包含:

  • 设备列表展示
  • 设备添加/编辑/删除
  • 设备状态监控
  • 批量操作功能

解决方案: 使用条件渲染和响应式布局策略:

<template>
<div class="device-page">
<!-- 桌面端:表格视图 -->
<el-table v-if="!isMobile"
:data="devices">
<!-- 表格列定义 -->
</el-table>
<!-- 移动端:卡片列表视图 -->
<div v-else
class="mobile-device-list">
<div v-for="device in devices"
:key="device.id"
class="device-card">
<!-- 卡片内容 -->
</div>
</div>
</div>
</template>

阶段四至六:登录、注册、个人信息界面整合#

登录界面#

  • 整合 Login.vue 和 MobileLogin.vue 为 LoginPage.vue
  • 代码量减少约180行

注册界面#

  • 整合 Register.vue 和 MobileRegister.vue 为 RegisterPage.vue
  • 代码量减少约82行

个人信息界面#

  • 整合 Profile.vue 和 MobileProfile.vue 为 ProfilePage.vue
  • 代码量减少约476行

共同的技术特点

  1. 使用 v-if=“!isMobile” 进行条件渲染
  2. 表单布局自适应:桌面端水平排列,移动端垂直堆叠
  3. 统一的状态管理和表单验证逻辑

阶段七:用户管理界面整合#

主要变更

  • 整合 UserManage.vue 和 MobileUserManage.vue
  • 优化用户列表展示和权限管理功能

技术细节

  • 桌面端使用 Element Plus 的 el-table 组件
  • 移动端使用自定义卡片列表
  • 统一的用户状态管理和权限控制

阶段八:备案信息组件整合#

主要变更

  • 删除独立的 MobileBeian.vue 组件
  • 将备案信息逻辑整合到 MobilePage.vue 中
  • 简化组件层级

阶段九:数据管理组件重构#

这是最复杂的重构之一,涉及:

  • 删除 MobileData.vue(1534行)
  • 重构 Data.vue 为响应式统一组件
  • 支持实时监控、数据分析、历史数据查询

技术亮点

  1. 平台检测
const shouldUseMobilePage = () => {
const width = window.innerWidth;
const isMobileDevice = /Android|webOS|
iPhone|iPad|iPod|BlackBerry|IEMobile|
Opera Mini/i.test(navigator.
userAgent);
return width < 768 || isMobileDevice;
};
  1. 差异化数据展示
// 桌面端显示24小时数据,移动端显示6小时数据
const timeRange = computed(() =>
isMobile.value ? 6 : 24);
  1. 移动端图表优化
// 移动端图表数据采样12个点优化显示
const chartData = computed(() => {
const data = rawData.value;
if (isMobile.value && data.length >
12) {
// 采样处理
const step = Math.ceil(data.
length / 12);
return data.filter((_, index) =>
index % step === 0);
}
return data;
});
  1. 历史数据展示差异化
<!-- 桌面端:表格 -->
<el-table v-if="!isMobile"
:data="historyData">
<!-- 表格列 -->
</el-table>
<!-- 移动端:卡片列表 -->
<div v-else class="history-cards">
<div v-for="item in historyData"
:key="item.id" class="history-card">
<!-- 卡片内容 -->
</div>
</div>

重构成果总结#

代码量变化#

重构阶段修改文件数代码变化
API层重构14-850行
总览组件整合6-1274行
设备界面整合5-389行
登录界面整合4-180行
注册界面整合5-82行
个人信息整合4-476行
用户管理整合3-631行
备案信息整合8-20行
数据管理整合3-513行

总计:代码减少约 4415 行

架构优化收益#

  1. 维护性提升:相同功能只需维护一份代码
  2. 一致性保证:双端界面风格和行为完全一致
  3. 开发效率:新功能开发工作量减少约50%
  4. Bug修复:修复一个问题只需修改一处代码
  5. 性能优化:减少了重复代码的加载和执行

关键技术方案#

  1. 响应式检测设备类型
const isMobile = computed(() => {
return window.innerWidth < 768 ||
/Android|webOS|iPhone|iPad|iPod|
BlackBerry|IEMobile|Opera Mini/i.
test(navigator.userAgent);
});
  1. 条件渲染策略
<template>
<div v-if="!isMobile"
class="desktop-view">
<!-- 桌面端特定内容 -->
</div>
<div v-else class="mobile-view">
<!-- 移动端特定内容 -->
</div>
</template>
  1. 差异化配置
const config = computed(() => ({
pageSize: isMobile.value ? 10 : 20,
chartPoints: isMobile.value ? 12 : 24,
showDetail: !isMobile.value
}));

遇到的挑战及解决方案#

挑战1:功能差异处理#

问题:某些功能在桌面端和移动端表现不同

解决方案

  • 使用 computed 属性动态计算配置
  • 保留核心逻辑一致,仅UI层差异化

挑战2:性能优化#

问题:移动端数据量大时性能下降

解决方案

  • 移动端数据采样(如历史数据只显示12个点)
  • 使用 v-memo 和 v-once 优化渲染
  • 懒加载非关键组件

挑战3:样式冲突#

问题:双端样式混合可能产生冲突

解决方案

  • 使用 BEM 命名规范
  • 添加平台特定类名前缀
  • CSS 模块化

总结#

通过这次系统性的重构,我们成功将一个双端分离的代码库转变为现代化的响应式架构。关键经验包括:

  1. 先统一基础设施:API层的统一是后续组件整合的基础
  2. 渐进式重构:分阶段进行,每个阶段都有明确目标
  3. 保持功能完整:每次重构后都进行完整测试
  4. 代码复用优先:提取公共逻辑,减少重复代码
分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Vue3 前端架构重构实践
http://www.cyanbutterfly.top/posts/vue3-frontend-architecture-refactoring/
作者
青蝶半染
发布于
2026-04-02
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时