uni-app 架构设计

章节简介

架构设计是 uni-app 应用开发的重要环节,它决定了应用的可扩展性、可维护性和性能表现。本章节将详细介绍 uni-app 架构设计的核心知识点,包括架构模式选择、模块划分、技术选型等,并通过实际案例演示如何设计一个合理的 uni-app 应用架构。

核心知识点

1. 架构模式选择

1.1 常见架构模式

  • MVC 模式:Model-View-Controller,将应用分为数据模型、视图和控制器三个部分
  • MVP 模式:Model-View-Presenter,在 MVC 基础上引入 Presenter 层,负责处理业务逻辑
  • MVVM 模式:Model-View-ViewModel,通过数据绑定实现视图与数据的自动同步
  • Flux/Redux 模式:单向数据流架构,适用于复杂状态管理

1.2 uni-app 中的架构选择

uni-app 推荐使用 MVVM 模式,结合 Vue.js 的响应式数据绑定特性,实现高效的开发体验:

  • Model:数据模型,负责数据的获取和处理
  • View:视图层,负责界面展示
  • ViewModel:视图模型,连接 Model 和 View,处理业务逻辑

2. 模块划分

2.1 合理的模块划分原则

  • 单一职责原则:每个模块只负责一个功能领域
  • 高内聚低耦合:模块内部紧密相关,模块之间松耦合
  • 可扩展性:便于添加新功能和修改现有功能
  • 可测试性:便于单元测试和集成测试

2.2 uni-app 项目结构设计

src/
├── components/          # 公共组件
├── pages/               # 页面
├── static/              # 静态资源
├── store/               # 状态管理
├── services/            # API 服务
├── utils/               # 工具函数
├── config/              # 配置文件
├── mixins/              # 混入
├── filters/             # 过滤器
├── router/              # 路由配置
└── App.vue              # 应用入口

3. 技术选型

3.1 状态管理

  • Vuex:官方推荐的状态管理库,适用于复杂应用
  • Pinia:Vue 3 推荐的状态管理库,API 更简洁
  • 简单状态管理:使用 Vue 实例的 data 或 provide/inject

3.2 网络请求

  • uni.request:uni-app 内置的网络请求 API
  • axios:第三方 HTTP 客户端,功能丰富
  • 封装请求:基于 uni.request 封装统一的请求模块

3.3 UI 组件库

  • uni-ui:DCloud 官方组件库,与 uni-app 深度集成
  • uView:社区流行的组件库,功能丰富
  • 自定义组件:根据业务需求开发专用组件

3.4 工具库

  • lodash:实用的 JavaScript 工具库
  • dayjs:轻量级日期处理库
  • validator:表单验证库

实用案例分析

案例:设计一个电商应用架构

1. 架构设计目标

  • 支持多端运行(小程序、App、H5)
  • 良好的可扩展性,便于添加新功能
  • 高效的开发和维护体验
  • 良好的性能表现

2. 架构模式选择

采用 MVVM 模式 + Vuex 状态管理

  • Model:通过 API 服务获取数据
  • View:使用 uni-app 页面和组件
  • ViewModel:Vue 实例和 Vuex store

3. 模块划分实现

src/
├── components/          # 公共组件
│   ├── header/          # 头部组件
│   ├── footer/          # 底部组件
│   ├── goods-card/      # 商品卡片组件
│   └── search-bar/      # 搜索栏组件
├── pages/               # 页面
│   ├── index/           # 首页
│   ├── goods/           # 商品详情页
│   ├── cart/            # 购物车页
│   ├── order/           # 订单页
│   └── user/            # 个人中心页
├── store/               # 状态管理
│   ├── modules/         # 模块状态
│   │   ├── goods.js     # 商品状态
│   │   ├── cart.js      # 购物车状态
│   │   ├── order.js     # 订单状态
│   │   └── user.js      # 用户状态
│   └── index.js         # 状态管理入口
├── services/            # API 服务
│   ├── api.js           # API 配置
│   ├── goods.js         # 商品相关 API
│   ├── cart.js          # 购物车相关 API
│   ├── order.js         # 订单相关 API
│   └── user.js          # 用户相关 API
├── utils/               # 工具函数
│   ├── request.js       # 请求封装
│   ├── storage.js       # 存储工具
│   └── validator.js     # 验证工具
├── config/              # 配置文件
│   ├── index.js         # 全局配置
│   └── api.js           # API 配置
└── App.vue              # 应用入口

4. 技术选型实现

  • 状态管理:Vuex,按功能模块划分状态
  • 网络请求:封装 uni.request,实现统一的请求处理
  • UI 组件:结合 uni-ui 和自定义组件
  • 工具库:按需引入 dayjs、lodash 等工具库

5. 架构设计文档

创建架构设计文档,记录架构决策和设计思路:

# 电商应用架构设计文档

## 1. 架构概述
- 采用 MVVM 架构模式
- 使用 Vuex 进行状态管理
- 模块化设计,高内聚低耦合

## 2. 目录结构
- 详细说明各目录的职责和内容

## 3. 核心模块设计
- 商品模块:商品列表、详情、搜索
- 购物车模块:添加商品、修改数量、结算
- 订单模块:创建订单、订单列表、订单详情
- 用户模块:登录、注册、个人信息

## 4. 技术选型
- 前端框架:uni-app
- 状态管理:Vuex
- 网络请求:封装 uni.request
- UI 组件:uni-ui + 自定义组件

## 5. 性能优化策略
- 代码分包:小程序分包加载
- 图片优化:懒加载、压缩
- 网络优化:请求缓存、合并请求
- 渲染优化:虚拟列表、减少重绘

## 6. 扩展性考虑
- 插件机制:便于功能扩展
- 配置化:通过配置实现灵活定制
- 模块化:便于团队协作开发

代码示例

1. 状态管理模块设计

store/modules/goods.js

// 商品状态管理
const state = {
  goodsList: [],
  goodsDetail: null,
  loading: false,
  error: null
};

const mutations = {
  SET_GOODS_LIST(state, list) {
    state.goodsList = list;
  },
  SET_GOODS_DETAIL(state, detail) {
    state.goodsDetail = detail;
  },
  SET_LOADING(state, loading) {
    state.loading = loading;
  },
  SET_ERROR(state, error) {
    state.error = error;
  }
};

const actions = {
  // 获取商品列表
  async getGoodsList({ commit }, params) {
    commit('SET_LOADING', true);
    try {
      const response = await uni.request({
        url: '/api/goods/list',
        method: 'GET',
        data: params
      });
      commit('SET_GOODS_LIST', response.data);
      commit('SET_ERROR', null);
    } catch (error) {
      commit('SET_ERROR', error.message);
    } finally {
      commit('SET_LOADING', false);
    }
  },
  
  // 获取商品详情
  async getGoodsDetail({ commit }, id) {
    commit('SET_LOADING', true);
    try {
      const response = await uni.request({
        url: `/api/goods/${id}`,
        method: 'GET'
      });
      commit('SET_GOODS_DETAIL', response.data);
      commit('SET_ERROR', null);
    } catch (error) {
      commit('SET_ERROR', error.message);
    } finally {
      commit('SET_LOADING', false);
    }
  }
};

const getters = {
  goodsList: state => state.goodsList,
  goodsDetail: state => state.goodsDetail,
  loading: state => state.loading,
  error: state => state.error
};

export default {
  namespaced: true,
  state,
  mutations,
  actions,
  getters
};

2. API 服务封装

services/api.js

// API 服务基础配置
const baseURL = 'https://api.example.com';

// 请求拦截器
const requestInterceptor = (config) => {
  // 添加 token
  const token = uni.getStorageSync('token');
  if (token) {
    config.header = {
      ...config.header,
      'Authorization': `Bearer ${token}`
    };
  }
  return config;
};

// 响应拦截器
const responseInterceptor = (response) => {
  if (response.statusCode === 200) {
    return response.data;
  } else {
    throw new Error(`请求失败:${response.statusCode}`);
  }
};

// 封装请求方法
const request = async (config) => {
  try {
    // 应用请求拦截器
    const interceptedConfig = requestInterceptor({
      url: `${baseURL}${config.url}`,
      method: config.method || 'GET',
      data: config.data,
      header: config.header || {},
      ...config
    });
    
    // 发起请求
    const response = await uni.request(interceptedConfig);
    
    // 应用响应拦截器
    return responseInterceptor(response[1]);
  } catch (error) {
    console.error('请求错误:', error);
    throw error;
  }
};

// 导出 API 方法
export default {
  get: (url, params, config) => request({ url, method: 'GET', data: params, ...config }),
  post: (url, data, config) => request({ url, method: 'POST', data, ...config }),
  put: (url, data, config) => request({ url, method: 'PUT', data, ...config }),
  delete: (url, params, config) => request({ url, method: 'DELETE', data: params, ...config })
};

3. 页面组件设计

pages/goods-detail/index.vue

<template>
  <view class="goods-detail">
    <!-- 商品图片 -->
    <view class="goods-images">
      <image 
        v-for="(image, index) in goodsDetail.images" 
        :key="index" 
        :src="image" 
        mode="aspectFill"
      ></image>
    </view>
    
    <!-- 商品信息 -->
    <view class="goods-info">
      <text class="goods-price">{{ goodsDetail.price }}</text>
      <text class="goods-title">{{ goodsDetail.title }}</text>
      <text class="goods-desc">{{ goodsDetail.description }}</text>
    </view>
    
    <!-- 商品参数 -->
    <view class="goods-params">
      <view class="param-item" v-for="(param, key) in goodsDetail.params" :key="key">
        <text class="param-label">{{ key }}:</text>
        <text class="param-value">{{ param }}</text>
      </view>
    </view>
    
    <!-- 底部操作栏 -->
    <view class="bottom-bar">
      <view class="action-btn" @click="addToCart">
        <text>加入购物车</text>
      </view>
      <view class="action-btn primary" @click="buyNow">
        <text>立即购买</text>
      </view>
    </view>
  </view>
</template>

<script>
import { mapState, mapActions } from 'vuex';

export default {
  data() {
    return {
      goodsId: this.$route.params.id
    };
  },
  computed: {
    ...mapState('goods', ['goodsDetail', 'loading', 'error'])
  },
  onLoad() {
    // 获取商品详情
    this.getGoodsDetail(this.goodsId);
  },
  methods: {
    ...mapActions('goods', ['getGoodsDetail']),
    
    // 加入购物车
    addToCart() {
      // 调用购物车相关 action
      this.$store.dispatch('cart/addToCart', this.goodsDetail);
      uni.showToast({ title: '已加入购物车', icon: 'success' });
    },
    
    // 立即购买
    buyNow() {
      // 跳转到订单确认页
      uni.navigateTo({
        url: `/pages/order-confirm/index?goodsId=${this.goodsId}`
      });
    }
  }
};
</script>

<style scoped>
/* 样式省略 */
</style>

章节总结

本章节详细介绍了 uni-app 应用的架构设计方法,包括:

  1. 架构模式选择:推荐使用 MVVM 模式,结合 Vue.js 的响应式数据绑定
  2. 模块划分:遵循单一职责原则,设计合理的项目结构
  3. 技术选型:根据应用需求选择合适的状态管理、网络请求和 UI 组件库
  4. 实用案例:通过电商应用架构设计案例,演示如何应用架构设计原则

通过合理的架构设计,可以显著提高 uni-app 应用的可扩展性、可维护性和性能表现,为后续的开发和迭代打下坚实的基础。

思考与练习

  1. 思考:根据你的项目需求,选择合适的架构模式和技术栈
  2. 练习:设计一个 uni-app 应用的架构方案,包括模块划分、技术选型和文件结构
  3. 实践:基于设计的架构方案,实现一个简单的 uni-app 应用

扩展阅读

« 上一篇 uni-app 需求分析 下一篇 » uni-app 原型设计