vue-typescript-admin-template中的架构设计模式:MVVM与Clean Architecture

vue-typescript-admin-template中的架构设计模式:MVVM与Clean Architecture

【免费下载链接】vue-typescript-admin-template 🖖 A vue-cli 3.0 + typescript minimal admin template 【免费下载链接】vue-typescript-admin-template 项目地址: https://gitcode.com/gh_mirrors/vu/vue-typescript-admin-template

引言:前端架构的痛点与解决方案

在现代前端开发中,随着应用规模的扩大和复杂度的提升,架构设计变得越来越重要。你是否还在为以下问题困扰?代码耦合严重,修改一个功能牵一发而动全身;业务逻辑与UI操作混杂,难以维护;测试困难,组件与数据层纠缠不清。本文将深入剖析vue-typescript-admin-template项目如何融合MVVM(Model-View-ViewModel)模式与Clean Architecture架构思想,为你提供一套清晰、可维护、可扩展的前端架构解决方案。

读完本文,你将能够:

  • 理解MVVM模式在Vue项目中的具体实现
  • 掌握Clean Architecture在前端的应用方法
  • 学会如何设计松耦合、高内聚的前端架构
  • 提升代码的可维护性和可测试性

项目架构概览

vue-typescript-admin-template是一个基于Vue CLI 3.0和TypeScript的最小化管理系统模板。项目采用了MVVM架构模式,并融入了Clean Architecture的思想,形成了清晰的分层结构。

整体架构图

mermaid

目录结构解析

项目的目录结构如下:

src/
├── api/            # API调用(基础设施层)
├── assets/         # 静态资源
├── components/     # 通用组件(表现层)
├── directives/     # 自定义指令
├── filters/        # 过滤器
├── icons/          # 图标
├── lang/           # 国际化
├── layout/         # 布局组件
├── router/         # 路由配置(应用层)
├── store/          # Vuex状态管理(应用层)
├── styles/         # 样式
├── utils/          # 工具函数(基础设施层)
├── views/          # 页面组件(表现层)
├── App.vue         # 根组件
├── main.ts         # 入口文件
└── permission.ts   # 权限控制

MVVM模式在项目中的实现

MVVM(Model-View-ViewModel)是一种软件架构模式,它将应用程序分为三个主要部分:模型(Model)、视图(View)和视图模型(ViewModel)。

MVVM架构图

mermaid

View层:Vue组件

在本项目中,View层由Vue组件构成,包括页面组件(views/)和通用组件(components/)。

以Dashboard页面为例:

<template>
  <div class="dashboard-container">
    <component :is="currentRole" />
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import { UserModule } from '@/store/modules/user'
import AdminDashboard from './admin/index.vue'
import EditorDashboard from './editor/index.vue'

@Component({
  name: 'Dashboard',
  components: {
    AdminDashboard,
    EditorDashboard
  }
})
export default class extends Vue {
  private currentRole = 'admin-dashboard'

  get roles() {
    return UserModule.roles
  }

  created() {
    if (!this.roles.includes('admin')) {
      this.currentRole = 'editor-dashboard'
    }
  }
}
</script>

这个组件根据用户角色动态渲染不同的仪表盘组件,体现了View层的职责:展示数据和处理用户交互。

ViewModel层:Vuex Store

Vuex Store充当了ViewModel的角色,它连接View和Model,负责数据的管理和业务逻辑的处理。

store/index.ts:

import Vue from 'vue'
import Vuex from 'vuex'
import { IAppState } from './modules/app'
import { IUserState } from './modules/user'
// ...其他导入

Vue.use(Vuex)

export interface IRootState {
  app: IAppState
  user: IUserState
  // ...其他状态
}

export default new Vuex.Store<IRootState>({})

以用户模块为例,展示ViewModel如何处理业务逻辑:

@Module({ dynamic: true, store, name: 'user' })
class User extends VuexModule implements IUserState {
  public token = getToken() || ''
  public name = ''
  public avatar = ''
  public roles: string[] = []

  @Mutation
  private SET_TOKEN(token: string) {
    this.token = token
  }

  @Action
  public async Login(userInfo: { username: string, password: string}) {
    let { username, password } = userInfo
    username = username.trim()
    const { data } = await login({ username, password })
    setToken(data.accessToken)
    this.SET_TOKEN(data.accessToken)
  }

  @Action
  public async GetUserInfo() {
    if (this.token === '') {
      throw Error('GetUserInfo: token is undefined!')
    }
    const { data } = await getUserInfo({ /* 参数 */ })
    const { roles, name, avatar } = data.user
    this.SET_ROLES(roles)
    this.SET_NAME(name)
    this.SET_AVATAR(avatar)
  }
  
  // ...其他Action和Mutation
}

Model层:数据与业务逻辑

Model层包括两部分:

  1. 服务端返回的数据模型
  2. 封装的业务逻辑

在本项目中,Model层的实现较为分散,主要体现在:

  • API调用(api/目录)
  • 工具函数(utils/目录)
  • Vuex模块中的业务逻辑

以用户API为例:

// api/users.ts
import request from '@/utils/request'

export const getUsers = (params: any) =>
  request({
    url: '/users',
    method: 'get',
    params
  })

export const login = (data: any) =>
  request({
    url: '/users/login',
    method: 'post',
    data
  })

// ...其他API

数据绑定:Vue的响应式系统

Vue的响应式系统实现了View和ViewModel之间的双向绑定。当ViewModel中的数据发生变化时,View会自动更新;反之,用户在View上的操作也会同步到ViewModel中。

以AdminDashboard组件为例:

<template>
  <div class="dashboard-editor-container">
    <line-chart :chart-data="lineChartData" />
    <panel-group @handle-set-line-chart-data="handleSetLineChartData" />
  </div>
</template>

<script lang="ts">
// ...导入

@Component({
  components: { LineChart, PanelGroup }
})
export default class extends Vue {
  private lineChartData = lineChartData.newVisitis

  private handleSetLineChartData(type: string) {
    this.lineChartData = lineChartData[type]
  }
}
</script>

当用户点击PanelGroup组件中的按钮时,会触发handleSetLineChartData方法,更新lineChartData,从而自动更新LineChart组件的展示。

Clean Architecture在项目中的体现

Clean Architecture(整洁架构)强调依赖规则:内层不依赖外层,外层依赖内层。架构从内到外分为:实体(Entities)、用例(Use Cases)、接口适配器(Interface Adapters)和外部接口(Frameworks & Drivers)。

Clean Architecture分层图

mermaid

实体层(Entities)

实体层包含业务实体和核心业务规则。在本项目中,实体层的体现较弱,主要包括:

  • TypeScript类型定义
  • 核心业务逻辑(如权限控制)

用例层(Use Cases)

用例层包含应用程序的具体业务流程。在本项目中,用例层主要由Vuex的Action实现:

// store/modules/user.ts 中的Action
@Action
public async Login(userInfo: { username: string, password: string}) {
  // 登录用例
  let { username, password } = userInfo
  username = username.trim()
  const { data } = await login({ username, password })
  setToken(data.accessToken)
  this.SET_TOKEN(data.accessToken)
}

@Action
public async LogOut() {
  // 登出用例
  if (this.token === '') {
    throw Error('LogOut: token is undefined!')
  }
  await logout()
  removeToken()
  resetRouter()
  this.SET_TOKEN('')
  this.SET_ROLES([])
}

接口适配器层(Interface Adapters)

接口适配器层负责将内层与外层进行适配。在本项目中,这一层包括:

  • Vuex的Mutation(将用例结果适配到状态)
  • 组件(将状态适配到视图)
  • API调用函数(将外部API适配到用例)

以API请求适配器为例:

// utils/request.ts
import axios from 'axios'
import { Message, MessageBox } from 'element-ui'
import { UserModule } from '@/store/modules/user'

const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API,
  timeout: 5000
})

// 请求拦截器
service.interceptors.request.use(
  (config) => {
    if (UserModule.token) {
      config.headers['X-Access-Token'] = UserModule.token
    }
    return config
  },
  (error) => {
    Promise.reject(error)
  }
)

// 响应拦截器
service.interceptors.response.use(
  (response) => {
    const res = response.data
    if (res.code !== 20000) {
      Message({
        message: res.message || 'Error',
        type: 'error',
        duration: 5 * 1000
      })
      // 错误处理逻辑
      return Promise.reject(new Error(res.message || 'Error'))
    } else {
      return response.data
    }
  },
  (error) => {
    Message({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)

export default service

外部接口层(Frameworks & Drivers)

外部接口层包括框架、库、UI组件等。本项目使用的外部资源有:

  • Vue框架
  • Element UI组件库
  • Axios网络请求库
  • ECharts图表库

MVVM与Clean Architecture的结合

架构映射关系

MVVM和Clean Architecture并不是互斥的,它们可以相互补充:

mermaid

数据流向

在结合了MVVM和Clean Architecture的项目中,数据流向如下:

mermaid

以用户登录为例:

mermaid

实际应用与最佳实践

状态管理最佳实践

  1. 模块化:按业务领域划分Vuex模块
// store/index.ts
export default new Vuex.Store<IRootState>({})

// store/modules/app.ts
@Module({ dynamic: true, store, name: 'app' })
export class App extends VuexModule implements IAppState {
  // ...
}

// store/modules/user.ts
@Module({ dynamic: true, store, name: 'user' })
export class User extends VuexModule implements IUserState {
  // ...
}
  1. 严格类型检查:使用TypeScript定义状态接口
export interface IUserState {
  token: string
  name: string
  avatar: string
  introduction: string
  roles: string[]
  email: string
}

@Module({ dynamic: true, store, name: 'user' })
class User extends VuexModule implements IUserState {
  public token = getToken() || ''
  public name = ''
  public avatar = ''
  public introduction = ''
  public roles: string[] = []
  public email = ''
  
  // ...
}

组件设计最佳实践

  1. 容器组件与展示组件分离

容器组件:负责数据获取和状态管理 展示组件:负责UI渲染和用户交互

以Dashboard为例:

views/dashboard/
├── index.vue         # 容器组件
├── admin/            # Admin视图
│   ├── index.vue     # 容器组件
│   └── components/   # 展示组件
└── editor/           # Editor视图
    ├── index.vue     # 容器组件
    └── components/   # 展示组件
  1. 组件通信
  • 父子组件:props和事件
  • 跨组件:Vuex或EventBus
  • 路由间通信:路由参数或Vuex

权限控制实现

项目中的权限控制是一个很好的用例实现:

// permission.ts
import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { getToken } from '@/utils/cookies'

const whiteList = ['/login', '/auth-redirect']

router.beforeEach(async(to, from, next) => {
  NProgress.start()
  if (getToken()) {
    if (to.path === '/login') {
      next({ path: '/' })
      NProgress.done()
    } else {
      if (store.getters.roles.length === 0) {
        try {
          await store.dispatch('user/GetUserInfo')
          const roles = store.getters.roles
          store.dispatch('permission/GenerateRoutes', { roles }).then(() => {
            router.addRoutes(store.getters.dynamicRoutes)
            next({ ...to, replace: true })
          })
        } catch (err) {
          store.dispatch('user/ResetToken').then(() => {
            Message.error(err || 'Has Error')
            next(`/login?redirect=${to.path}`)
            NProgress.done()
          })
        }
      } else {
        next()
      }
    }
  } else {
    if (whiteList.indexOf(to.path) !== -1) {
      next()
    } else {
      next(`/login?redirect=${to.path}`)
      NProgress.done()
    }
  }
})

router.afterEach(() => {
  NProgress.done()
})

项目架构的优缺点分析

优点

  1. 清晰的职责分离:MVVM模式使UI、业务逻辑和数据模型分离
  2. 可测试性:Vuex的Action和Mutation易于单元测试
  3. 松耦合:Clean Architecture的依赖规则减少了组件间的耦合
  4. 可维护性:模块化和分层设计使代码更易于维护
  5. TypeScript支持:强类型提高了代码质量和开发效率

缺点

  1. 学习曲线陡峭:同时理解MVVM和Clean Architecture有一定难度
  2. 样板代码较多:Vuex的使用需要编写Action、Mutation等
  3. 状态管理复杂度:对于小型应用,Vuex可能显得过重
  4. Model层弱化:业务逻辑分散在Vuex中,缺乏集中的领域模型

改进建议

  1. 引入领域模型:将分散的业务逻辑封装到专门的领域模型中
  2. 使用Composition API:Vue 3的Composition API可以更好地组织代码
  3. 引入数据仓库模式:统一管理数据获取和缓存
  4. 加强TypeScript类型定义:为API响应和业务实体创建更完善的类型

总结与展望

vue-typescript-admin-template项目融合了MVVM和Clean Architecture的思想,构建了一个结构清晰、可维护的前端架构。通过Vuex实现的ViewModel层有效地连接了View和Model,同时遵循了Clean Architecture的依赖规则。

随着前端技术的发展,未来可以考虑:

  1. 微前端架构:将大型应用拆分为更小的、自治的前端应用
  2. 状态管理方案演进:探索Pinia等新一代状态管理库
  3. 更好的领域驱动设计:引入更完善的领域模型和用例设计
  4. 服务端渲染/静态生成:提升性能和SEO

通过不断优化架构,我们可以构建出更健壮、更可维护的前端应用,为用户提供更好的体验。

参考资源

  1. Vue官方文档: https://vuejs.org/
  2. Vuex官方文档: https://vuex.vuejs.org/
  3. Clean Architecture by Robert C. Martin
  4. Vue-TypeScript-Admin-Template项目源码

【免费下载链接】vue-typescript-admin-template 🖖 A vue-cli 3.0 + typescript minimal admin template 【免费下载链接】vue-typescript-admin-template 项目地址: https://gitcode.com/gh_mirrors/vu/vue-typescript-admin-template

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值