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 应用的架构设计方法,包括:
- 架构模式选择:推荐使用 MVVM 模式,结合 Vue.js 的响应式数据绑定
- 模块划分:遵循单一职责原则,设计合理的项目结构
- 技术选型:根据应用需求选择合适的状态管理、网络请求和 UI 组件库
- 实用案例:通过电商应用架构设计案例,演示如何应用架构设计原则
通过合理的架构设计,可以显著提高 uni-app 应用的可扩展性、可维护性和性能表现,为后续的开发和迭代打下坚实的基础。
思考与练习
- 思考:根据你的项目需求,选择合适的架构模式和技术栈
- 练习:设计一个 uni-app 应用的架构方案,包括模块划分、技术选型和文件结构
- 实践:基于设计的架构方案,实现一个简单的 uni-app 应用