掌握uni-app项目结构就像学开车前先熟悉车内布局,看似繁琐却能让你在开发路上游刃有余。本文用大量图表和实战案例,帮你彻底搞懂uni-app项目的"五脏六腑"。
当你创建第一个uni-app项目时,看到的目录结构可能是这样的:
my-uni-app/
├── pages/ # 页面文件目录
│ ├── index/
│ │ ├── index.vue # 首页
│ │ └── components/ # 页面私有组件
│ └── detail/
│ └── detail.vue # 详情页
├── static/ # 静态资源目录
│ ├── images/
│ │ ├── logo.png
│ │ └── banners/
│ └── icons/
├── components/ # 全局组件目录
│ ├── base/ # 基础组件
│ └── business/ # 业务组件
├── uni_modules/ # 插件市场模块
├── wxcomponents/ # 微信小程序原生组件
├── App.vue # 应用配置和全局样式
├── main.js # 应用入口文件
├── manifest.json # 应用配置文件
├── pages.json # 页面路由和样式配置
└── uni.scss # 全局样式变量
项目结构关系图:
┌─────────────────────────────────────────────────────────────┐
│ uni-app项目结构关系图 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ manifest │ │ pages.json│ │ App.vue │ │
│ │ .json │ │ │ │ │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ ┌──────┴──────────────────┴──────────────────┴──────┐ │
│ │ 应用配置层 (Configuration) │ │
│ └──────────────────────────┬─────────────────────────┘ │
│ │ │
│ ┌──────────────────────────┼─────────────────────────┐ │
│ │ 框架层 (Framework) │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ main.js │ │ uni.scss │ │ pages/ │ │ │
│ │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │ │
│ └─────────┼────────────────┼────────────────┼────────┘ │
│ │ │ │ │
│ ┌─────────┴────────────────┴────────────────┴────────┐ │
│ │ 业务层 (Business) │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ components/ │ │ static/ │ │uni_modules/ │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ └────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
如果把目录结构比作一家公司,那么每个目录的作用如下:
pages/ - 各个部门办公室(每个页面都是独立部门)
static/ - 公司仓库(存放不会变动的资产)
components/ - 标准化工作台(可复用的工具和模板)
uni_modules/ - 外包服务团队(第三方功能模块)
App.vue - 总经理办公室(全局决策和管理)
main.js - 公司大门(所有人进入公司的入口)
manifest.json - 公司营业执照(应用身份证明)
pages.json - 公司组织架构图(页面关系和样式规范)
实战项目中,推荐的目录结构如下:
src/
├── api/ # API接口层
│ ├── index.js # 请求拦截器和全局配置
│ ├── user.js # 用户相关接口
│ ├── product.js # 商品相关接口
│ └── order.js # 订单相关接口
├── common/ # 公共资源
│ ├── css/ # 公共样式
│ │ ├── reset.scss # 样式重置
│ │ ├── variables.scss # 样式变量
│ │ └── mixins.scss # 样式混合
│ ├── js/ # 工具函数
│ │ ├── utils.js # 通用工具
│ │ ├── validate.js # 表单验证
│ │ └── constants.js # 常量定义
│ └── filters/ # 全局过滤器
├── components/ # 组件库
│ ├── base/ # 基础组件
│ │ ├── button/ # 按钮组件
│ │ ├── input/ # 输入框组件
│ │ └── modal/ # 弹窗组件
│ └── business/ # 业务组件
│ ├── user-card/ # 用户卡片
│ ├── product-list/# 商品列表
│ └── order-item/ # 订单项
├── pages/ # 页面目录
│ ├── home/ # 首页模块
│ │ ├── home.vue # 首页
│ │ └── components/ # 首页专用组件
│ ├── user/ # 用户模块
│ │ ├── login/ # 登录页
│ │ ├── profile/ # 个人资料
│ │ └── settings/ # 设置页
│ └── product/ # 商品模块
│ ├── list/ # 商品列表
│ ├── detail/ # 商品详情
│ └── search/ # 商品搜索
├── store/ # 状态管理(Vuex)
│ ├── index.js # store入口文件
│ ├── modules/ # 模块化store
│ │ ├── user.js # 用户状态
│ │ ├── product.js # 商品状态
│ │ └── cart.js # 购物车状态
│ └── types.js # 类型常量
├── utils/ # 工具函数
│ ├── request.js # 网络请求封装
│ ├── storage.js # 缓存管理
│ ├── auth.js # 权限管理
│ └── router.js # 路由工具
└── static/ # 静态资源
├── images/
│ ├── common/ # 公共图片
│ ├── icons/ # 图标
│ └── banners/ # 广告图
├── fonts/ # 字体文件
└── json/ # 静态数据
目录结构设计原则:
┌─────────────────────────────────────────────────────────────┐
│ 目录设计原则 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 单一职责原则 高内聚低耦合 易于维护扩展 │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ 每个目录只 │ │ 相关功能放 │ │ 新功能容易 │ │
│ │ 做一件事 │ │ 在同一目录 │ │ 添加和修改 │ │
│ └────────────┘ └────────────┘ └────────────┘ │
│ │
│ 分层清晰明确 按功能模块化 团队协作友好 │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ API/组件/ │ │ 用户/商品/ │ │ 不同开发者 │ │
│ │ 页面分离 │ │ 订单分模块 │ │ 负责不同模块│ │
│ └────────────┘ └────────────┘ └────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
pages.json 是uni-app的路由中枢和样式调度中心,它决定了:
pages.json 配置流程图:
下面以一个电商应用为例,完整
pages.json 配置如下:
{
// ==================== 全局样式配置 ====================
"globalStyle": {
// 导航栏相关
"navigationBarTextStyle": "white", // 标题文字颜色
"navigationBarTitleText": "智能商城", // 默认标题
"navigationBarBackgroundColor": "#FF6B35", // 导航栏背景色
"backgroundColor": "#F8F8F8", // 窗口背景色
// 下拉刷新
"enablePullDownRefresh": false, // 默认关闭下拉刷新
"backgroundTextStyle": "dark", // 下拉loading样式
"onReachBottomDistance": 50, // 上拉触底距离
// 页面动画
"animationType": "pop-in", // 页面切换动画
"animationDuration": 300, // 动画时长
// H5配置
"h5": {
"titleNView": { // H5标题栏
"titleText": "智能商城",
"backgroundColor": "#FF6B35",
"titleColor": "#FFFFFF"
}
},
// App配置
"app-plus": {
"background": "#F8F8F8", // 应用背景色
"bounce": "vertical" // 回弹效果
}
},
// ==================== 页面路由配置 ====================
"pages": [
// 首页必须放在第一个位置!
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "智能商城首页",
"enablePullDownRefresh": true, // 首页开启下拉刷新
"backgroundTextStyle": "dark",
"navigationBarBackgroundColor": "#FF6B35",
// 首页特殊配置
"app-plus": {
"bounce": "vertical" // iOS回弹效果
}
}
},
// 分类页面
{
"path": "pages/category/category",
"style": {
"navigationBarTitleText": "商品分类",
"enablePullDownRefresh": false,
"navigationBarBackgroundColor": "#4CD964" // 绿色主题
}
},
// 购物车页面
{
"path": "pages/cart/cart",
"style": {
"navigationBarTitleText": "购物车",
"navigationBarBackgroundColor": "#FF9500" // 橙色主题
}
},
// 个人中心
{
"path": "pages/user/user",
"style": {
"navigationBarTitleText": "个人中心",
"navigationBarBackgroundColor": "#5856D6" // 紫色主题
}
},
// 商品详情页
{
"path": "pages/product/detail",
"style": {
"navigationBarTitleText": "商品详情",
"navigationBarBackgroundColor": "#FF6B35",
// 详情页禁用下拉刷新
"enablePullDownRefresh": false,
// 自定义配置
"app-plus": {
"bounce": "none" // 禁用回弹
}
}
}
],
// ==================== 底部TabBar配置 ====================
"tabBar": {
// 基础样式
"color": "#7F7F7F", // 默认颜色
"selectedColor": "#FF6B35", // 选中颜色
"backgroundColor": "#FFFFFF", // 背景色
"borderStyle": "black", // 边框颜色
"blurEffect": "none", // 毛玻璃效果(iOS)
// 图标和文字样式
"iconWidth": "24px", // 图标宽度
"spacing": "3px", // 图标与文字间距
"height": "50px", // TabBar高度
"fontSize": "10px", // 文字大小
// Tab项列表
"list": [
{
"pagePath": "pages/index/index", // 页面路径
"iconPath": "static/tabbar/home.png", // 默认图标
"selectedIconPath": "static/tabbar/home-active.png", // 选中图标
"text": "首页", // 文字
// 角标配置
"badge": "12", // 角标数字
"badgeStyle": "background-color: #FF3B30; color: #FFFFFF;" // 角标样式
},
{
"pagePath": "pages/category/category",
"iconPath": "static/tabbar/category.png",
"selectedIconPath": "static/tabbar/category-active.png",
"text": "分类",
"badge": "NEW", // 文字角标
"badgeStyle": "background-color: #4CD964; color: #FFFFFF;"
},
{
"pagePath": "pages/cart/cart",
"iconPath": "static/tabbar/cart.png",
"selectedIconPath": "static/tabbar/cart-active.png",
"text": "购物车",
"badge": "3", // 购物车商品数量
"badgeStyle": "background-color: #FF9500; color: #FFFFFF;"
},
{
"pagePath": "pages/user/user",
"iconPath": "static/tabbar/user.png",
"selectedIconPath": "static/tabbar/user-active.png",
"text": "我的"
}
],
// 中间凸起按钮
"midButton": {
"width": "50px", // 按钮宽度
"height": "50px", // 按钮高度
"text": "发布", // 按钮文字
"iconPath": "static/tabbar/add.png", // 按钮图标
"iconWidth": "25px", // 图标宽度
"backgroundImage": "" // 背景图片
}
},
// ==================== 组件自动引入配置 ====================
"easycom": {
"autoscan": true, // 开启自动扫描
"custom": {
// 自定义组件匹配规则
"^uni-(.*)": "@/components/uni-$1.vue", // uni-开头组件
"^my-(.*)": "@/components/my-$1.vue", // my-开头组件
"^base-(.*)": "@/components/base/$1.vue", // base-开头基础组件
"^biz-(.*)": "@/components/business/$1.vue" // biz-开头业务组件
}
},
// ==================== 条件编译配置 ====================
"condition": {
"current": 0, // 当前启动模式
"list": [
{
"name": "商品详情测试", // 模式名称
"path": "pages/product/detail", // 启动页面
"query": "id=1001&type=test" // 启动参数
},
{
"name": "订单列表测试",
"path": "pages/order/list",
"query": "status=1"
}
]
},
// ==================== 平台差异化配置 ====================
// H5平台配置
"h5": {
"publicPath": "/", // 静态资源路径
"router": {
"mode": "hash", // 路由模式: hash/history
"base": "./" // 路由基路径
},
"title": "智能商城H5版", // 页面标题
"template": "template.h5.html", // 自定义模板
"optimization": {
"treeShaking": {
"enable": true // 开启摇树优化
}
}
},
// 微信小程序专属配置
"mp-weixin": {
"appid": "wx1234567890abcdef", // 小程序AppID
"setting": {
"urlCheck": false, // 关闭域名校验
"es6": true, // 启用ES6转ES5
"enhance": true, // 增强编译
"postcss": true, // 样式自动补全
"minified": true // 代码压缩
},
"usingComponents": true, // 使用自定义组件
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序位置接口的效果展示"
}
},
"requiredPrivateInfos": [
"getLocation", // 需要的地理位置权限
"chooseAddress" // 需要的地址权限
]
},
// App平台专属配置
"app-plus": {
"usingComponents": true, // 使用自定义组件
"nvueStyleCompiler": "uni-app", // nvue样式编译器
"compilerVersion": 3, // 编译器版本
"splashscreen": {
"target": "id:1", // 启动图配置
"autoclose": true, // 自动关闭
"waiting": true, // 显示等待
"delay": 0 // 延迟关闭
},
"modules": { // 应用模块配置
"Camera": {},
"Gallery": {},
"Maps": {}
},
"distribute": {
"android": {
"packagename": "com.company.smartmall", // 包名
"permissions": [ // Android权限
"<uses-permission android:name="android.permission.CAMERA"/>",
"<uses-permission android:name="android.permission.INTERNET"/>"
]
},
"ios": {
"bundleidentifier": "com.company.SmartMall", // Bundle ID
"deploymentTarget": "11.0" // 最低支持版本
}
}
}
}
页面路径配置原理图:
┌─────────────────────────────────────────────────────────────┐
│ 页面路由配置原理 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 用户访问路径: /pages/index/index │
│ ↓ │
│ pages.json中查找匹配的path │
│ ↓ │
│ 找到配置: { path: "pages/index/index", style: {...} } │
│ ↓ │
│ 加载对应Vue文件: pages/index/index.vue │
│ ↓ │
│ 应用页面样式配置 │
│ ↓ │
│ 渲染页面到视图层 │
│ │
└─────────────────────────────────────────────────────────────┘
关键配置项说明:
{
"path": "pages/index/index",
"style": {
// 导航栏配置
"navigationBarTitleText": "首页", // 页面标题
"navigationBarBackgroundColor": "#FF6B35", // 导航栏背景色
"navigationBarTextStyle": "white", // 标题文字颜色
// 页面行为配置
"enablePullDownRefresh": true, // 启用下拉刷新
"onReachBottomDistance": 50, // 触底加载距离
"disableScroll": false, // 禁用页面滚动
// 背景相关配置
"backgroundColor": "#F8F8F8", // 页面背景色
"backgroundTextStyle": "dark", // 下拉loading样式
// 页面动画
"animationType": "slide-in-right", // 进入动画
"animationDuration": 300, // 动画时长
// 平台配置
"app-plus": {
"bounce": "vertical", // 回弹效果
"titleNView": { // 标题栏
"titleText": "首页",
"titleColor": "#FFFFFF"
}
},
"h5": {
"title": "首页 - 智能商城", // 浏览器标题
"template": "template.h5.html" // 自定义模板
}
}
}
下拉刷新是移动端常见需求,配置时需要特别注意:
{
"path": "pages/list/list",
"style": {
"enablePullDownRefresh": true, // 开启下拉刷新
"backgroundTextStyle": "dark", // loading样式: dark/light
"backgroundColor": "#F6F6F6", // 下拉区域背景色
// 微信小程序专属下拉刷新样式
"mp-weixin": {
"enablePullDownRefresh": true,
"onReachBottomDistance": 100,
"pullToRefresh": {
"color": "#007AFF", // loading颜色
"style": "circle" // 样式: circle/default
}
},
// App平台下拉刷新配置
"app-plus": {
"pullToRefresh": {
"support": true, // 支持下拉刷新
"color": "#007AFF", // 颜色
"style": "circle", // 样式
"height": "80px", // 下拉高度
"range": "100px", // 触发范围
"offset": "0px" // 偏移量
}
}
}
}
对应的页面逻辑处理:
// pages/list/list.vue
export default {
data() {
return {
list: [],
page: 1,
loading: false
}
},
// 下拉刷新处理
onPullDownRefresh() {
console.log('触发下拉刷新');
// 显示loading状态
this.loading = true;
// 重新加载数据
this.refreshData().then(() => {
// 停止下拉刷新动画
uni.stopPullDownRefresh();
this.loading = false;
// 显示成功提示
uni.showToast({
title: '刷新成功',
icon: 'success'
});
}).catch(error => {
// 停止下拉刷新
uni.stopPullDownRefresh();
this.loading = false;
// 显示错误提示
uni.showToast({
title: '刷新失败',
icon: 'none'
});
});
},
// 上拉触底处理
onReachBottom() {
console.log('触发上拉触底');
// 加载更多数据
this.loadMoreData();
},
methods: {
// 刷新数据
async refreshData() {
try {
// 重置页码
this.page = 1;
// 调用API获取数据
const response = await this.$api.getList({
page: this.page,
size: 10
});
// 更新列表数据
this.list = response.data.list;
} catch (error) {
console.error('刷新数据失败:', error);
throw error;
}
},
// 加载更多数据
async loadMoreData() {
// 防止重复加载
if (this.loading) return;
this.loading = true;
try {
this.page++;
const response = await this.$api.getList({
page: this.page,
size: 10
});
// 追加数据
this.list = [...this.list, ...response.data.list];
// 如果没有更多数据
if (response.data.list.length === 0) {
uni.showToast({
title: '没有更多数据了',
icon: 'none'
});
}
} catch (error) {
console.error('加载更多失败:', error);
this.page--;
} finally {
this.loading = false;
}
}
}
}
底部TabBar是应用导航的核心,配置时需要考虑用户体验:
TabBar配置架构图:
完整TabBar配置如下:
{
"tabBar": {
// ========== 基础样式配置 ==========
"color": "#7A7E83", // 默认文字颜色
"selectedColor": "#007AFF", // 选中文字颜色
"backgroundColor": "#FFFFFF", // 背景颜色
"borderStyle": "black", // 边框颜色
"blurEffect": "none", // 毛玻璃效果(iOS)
// ========== 尺寸和布局配置 ==========
"iconWidth": "24px", // 图标宽度
"spacing": "3px", // 图标文字间距
"height": "50px", // TabBar高度
"fontSize": "10px", // 文字大小
"selectedIndex": 0, // 默认选中索引
// ========== Tab项列表配置 ==========
"list": [
{
// 基础配置
"pagePath": "pages/index/index", // 页面路径
"iconPath": "static/tabbar/home.png", // 默认图标路径
"selectedIconPath": "static/tabbar/home-active.png", // 选中图标
"text": "首页", // 文字标签
// 角标配置
"badge": "12", // 角标内容
"badgeStyle": "background-color: #FF3B30; color: #FFFFFF; font-size: 10px;", // 角标样式
// 平台特定配置
"app-plus": {
"iconPath": "static/tabbar/home-ios.png", // iOS图标
"selectedIconPath": "static/tabbar/home-ios-active.png"
},
"mp-weixin": {
"iconPath": "static/tabbar/home-wechat.png", // 微信小程序图标
"selectedIconPath": "static/tabbar/home-wechat-active.png"
}
},
{
"pagePath": "pages/category/category",
"iconPath": "static/tabbar/category.png",
"selectedIconPath": "static/tabbar/category-active.png",
"text": "分类",
"badge": "NEW", // 文字角标
"badgeStyle": "background-color: #4CD964; color: #FFFFFF;"
},
{
"pagePath": "pages/cart/cart",
"iconPath": "static/tabbar/cart.png",
"selectedIconPath": "static/tabbar/cart-active.png",
"text": "购物车",
"badge": "3", // 购物车数量
"badgeStyle": "background-color: #FF9500; color: #FFFFFF;"
},
{
"pagePath": "pages/user/user",
"iconPath": "static/tabbar/user.png",
"selectedIconPath": "static/tabbar/user-active.png",
"text": "我的"
}
],
// ========== 中间凸起按钮配置 ==========
"midButton": {
"width": "50px", // 按钮宽度
"height": "50px", // 按钮高度
"text": "发布", // 按钮文字
"iconPath": "static/tabbar/add.png", // 按钮图标
"iconWidth": "25px", // 图标宽度
"backgroundImage": "", // 背景图片
"backgroundColor": "#007AFF", // 背景颜色
// 点击事件处理页面
"pagePath": "pages/publish/publish", // 跳转页面
// 平台特定配置
"app-plus": {
"height": "60px", // App端更高
"iconPath": "static/tabbar/add-ios.png"
}
},
// ========== 平台差异化配置 ==========
"app-plus": {
"height": "55px", // App端高度
"borderStyle": "white", // 边框样式
"blurEffect": "light", // 毛玻璃效果
"selectedIndex": 0
},
"mp-weixin": {
"color": "#7F7F7F",
"selectedColor": "#07C160", // 微信绿色
"backgroundColor": "#FFFFFF",
"borderStyle": "black"
},
"h5": {
"height": "50px",
"borderStyle": "#E5E5E5"
}
}
}
TabBar设计要点总结:
数量控制:3-5个Tab最为合适,太多会影响用户体验图标设计:简洁明了,选中状态要有明显变化文字标签:简短明确,一般2-4个汉字角标使用:重要通知使用数字角标,新功能使用文字角标平台适配:不同平台的TabBar高度和样式有所差异
manifest.json 是uni-app应用的身份证和功能说明书,它定义了:
manifest.json 配置架构图:
下面是一个完整的
manifest.json 配置示例:
{
// ==================== 应用基本信息 ====================
"name": "智能家居控制中心", // 应用名称
"appid": "__UNI__1234567", // 应用ID,创建项目时生成
"description": "一站式智能家居管理平台", // 应用描述
"versionName": "1.0.0", // 版本名称(用户可见)
"versionCode": "100", // 版本号(内部识别)
"type": "app", // 应用类型: app/h5
// ==================== 图标配置 ====================
"icons": {
"android": { // Android平台图标
"36": "static/icons/36x36.png", // LDPI - 36x36
"48": "static/icons/48x48.png", // MDPI - 48x48
"72": "static/icons/72x72.png", // HDPI - 72x72
"96": "static/icons/96x96.png", // XHDPI - 96x96
"144": "static/icons/144x144.png", // XXHDPI - 144x144
"192": "static/icons/192x192.png" // XXXHDPI - 192x192
},
"ios": { // iOS平台图标
"76": "static/icons/76x76.png", // iPad - 76x76
"120": "static/icons/120x120.png", // iPhone @2x - 120x120
"152": "static/icons/152x152.png", // iPad @2x - 152x152
"167": "static/icons/167x167.png", // iPad Pro - 167x167
"180": "static/icons/180x180.png" // iPhone @3x - 180x180
}
},
// ==================== 启动界面配置 ====================
"splashscreen": {
"alwaysShowBeforeRender": true, // 总是显示启动图
"waiting": true, // 显示等待界面
"autoclose": true, // 自动关闭启动图
"delay": 0, // 延迟关闭时间
// Android启动图配置
"android": {
"hdpi": "static/splash/android/hdpi.png", // 480x800
"xhdpi": "static/splash/android/xhdpi.png", // 720x1280
"xxhdpi": "static/splash/android/xxhdpi.png", // 1080x1920
"xxxhdpi": "static/splash/android/xxxhdpi.png" // 1440x2560
},
// iOS启动图配置
"ios": {
"iphone": {
"640x960": "static/splash/ios/640x960.png", // iPhone 4/4s
"640x1136": "static/splash/ios/640x1136.png", // iPhone 5/5s/SE
"750x1334": "static/splash/ios/750x1334.png", // iPhone 6/7/8
"1242x2208": "static/splash/ios/1242x2208.png", // iPhone 6+/7+/8+
"1125x2436": "static/splash/ios/1125x2436.png", // iPhone X/XS
"828x1792": "static/splash/ios/828x1792.png", // iPhone XR
"1242x2688": "static/splash/ios/1242x2688.png" // iPhone XS Max
},
"ipad": {
"768x1024": "static/splash/ios/768x1024.png", // iPad 非Retina
"1536x2048": "static/splash/ios/1536x2048.png" // iPad Retina
}
}
},
// ==================== 应用模块配置 ====================
"modules": {
"Camera": { // 相机模块
"description": "用于扫描设备二维码"
},
"Gallery": { // 相册模块
"description": "用于选择设备图片"
},
"Maps": { // 地图模块
"description": "用于设备位置定位"
},
"Push": { // 推送模块
"description": "用于接收设备通知"
},
"Payment": { // 支付模块
"description": "用于设备服务购买"
}
},
// ==================== 权限配置 ====================
"permissions": {
"Camera": {
// 权限描述
"describe": "用于扫描设备二维码"
},
"WritePhotosAlbum": {
"describe": "用于保存设备截图"
},
"Location": {
"describe": "用于获取设备位置信息"
},
"Notification": {
"describe": "用于接收设备推送通知"
}
},
// ==================== App平台配置 ====================
"app-plus": {
// 应用特性配置
"usingComponents": true, // 使用自定义组件
"nvueStyleCompiler": "uni-app", // nvue样式编译器
"compilerVersion": 3, // 编译器版本
"renderer": "auto", // 渲染模式
// 启动界面配置
"splashscreen": {
"target": "id:1", // 启动图配置
"autoclose": true, // 自动关闭
"waiting": true, // 显示等待
"delay": 0 // 延迟关闭
},
// 状态栏配置
"statusbar": {
"immersed": true, // 沉浸式状态栏
"style": "dark", // 状态栏样式: dark/light
"background": "#FF6B35" // 状态栏背景色
},
// 软键盘行为配置
"softinput": {
"mode": "adjustResize" // 键盘弹出模式
},
// 权限配置
"permissions": {
"UniNView": {
"description": "原生渲染"
}
},
// 打包配置
"distribute": {
"android": { // Android打包配置
"packagename": "com.smarthome.control", // 包名
"versionCode": "100", // 版本号
"versionName": "1.0.0", // 版本名称
"minSdkVersion": 21, // 最低SDK版本
"targetSdkVersion": 30, // 目标SDK版本
"permissions": [ // Android权限
"<uses-permission android:name="android.permission.CAMERA"/>",
"<uses-permission android:name="android.permission.INTERNET"/>",
"<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>",
"<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>"
],
"abiFilters": [ // CPU架构
"armeabi-v7a",
"arm64-v8a"
]
},
"ios": { // iOS打包配置
"bundleidentifier": "com.smarthome.ControlCenter", // Bundle ID
"version": "1.0.0", // 版本号
"build": "1", // 构建号
"deploymentTarget": "11.0", // 最低支持版本
"urltypes": [ // URL Scheme
{
"urlidentifier": "smarthome",
"urlschemes": [
"smarthome"
]
}
],
"privacyDescription": { // 隐私权限描述
"NSCameraUsageDescription": "用于扫描设备二维码",
"NSLocationWhenInUseUsageDescription": "用于获取设备位置信息",
"NSPhotoLibraryUsageDescription": "用于选择设备图片"
}
}
}
},
// ==================== H5平台配置 ====================
"h5": {
"publicPath": "/", // 静态资源路径
"router": {
"mode": "hash", // 路由模式: hash/history
"base": "./" // 路由基路径
},
"title": "智能家居控制中心", // 页面标题
"template": "template.h5.html", // 自定义模板
"optimization": {
"treeShaking": { // 摇树优化
"enable": true
}
},
"devServer": { // 开发服务器配置
"https": false, // 是否启用HTTPS
"port": 8080, // 端口号
"disableHostCheck": true, // 禁用主机检查
"proxy": { // 代理配置
"/api": {
"target": "https://api.smarthome.com",
"changeOrigin": true,
"secure": false,
"pathRewrite": {
"^/api": ""
}
}
}
}
},
// ==================== 微信小程序配置 ====================
"mp-weixin": {
"appid": "wx1234567890abcdef", // 小程序AppID
"setting": {
"urlCheck": false, // 关闭域名校验
"es6": true, // 启用ES6转ES5
"enhance": true, // 增强编译
"postcss": true, // 样式自动补全
"minified": true, // 代码压缩
"newFeature": true // 新特性支持
},
"usingComponents": true, // 使用自定义组件
"permission": { // 权限申请配置
"scope.userLocation": {
"desc": "你的位置信息将用于小程序位置接口的效果展示"
},
"scope.record": {
"desc": "你的录音功能将用于语音控制设备"
}
},
"requiredPrivateInfos": [ // 需要的隐私接口
"getLocation",
"chooseAddress",
"chooseLocation"
],
"plugins": { // 插件配置
"smartHomePlugin": {
"version": "1.0.0",
"provider": "wxidxxxxxxxxxxxx"
}
},
"navigateToMiniProgramAppIdList": [ // 可跳转的小程序
"wxdxxxxxxxxxxxxxx"
]
},
// ==================== 其他小程序配置 ====================
"mp-alipay": {
"usingComponents": true
},
"mp-baidu": {
"usingComponents": true
},
"mp-toutiao": {
"usingComponents": true
},
"mp-qq": {
"usingComponents": true
}
}
应用图标是用户的第一印象,配置时需要注意尺寸,格式为png即可:
图标尺寸规范表:
| 平台 | 设备类型 | 尺寸 | 用途 | 备注 |
|---|---|---|---|---|
| Android | LDPI | 36x36 | 低密度屏幕 | 已较少使用 |
| Android | MDPI | 48x48 | 中密度屏幕 | 基准尺寸 |
| Android | HDPI | 72x72 | 高密度屏幕 | 常见尺寸 |
| Android | XHDPI | 96x96 | 超高密度 | 主流尺寸 |
| Android | XXHDPI | 144x144 | 超超高密度 | 高端设备 |
| Android | XXXHDPI | 192x192 | 超超超高密度 | 最新设备 |
| iOS | iPhone | 120x120 | iPhone @2x | iPhone 6/7/8 |
| iOS | iPhone | 180x180 | iPhone @3x | iPhone 6+/7+/8+ |
| iOS | iPad | 76x76 | iPad 1x | 非Retina iPad |
| iOS | iPad | 152x152 | iPad @2x | Retina iPad |
启动图是用户打开应用时看到的第一屏,配置要细致,注意文件不能过大,否则影响启动速度:
"splashscreen": {
"alwaysShowBeforeRender": true, // 总是显示启动图
"waiting": true, // 显示等待界面
"autoclose": true, // 自动关闭启动图
"delay": 0, // 延迟关闭时间(ms)
"android": {
"hdpi": "static/splash/hdpi.png", // 480x800
"xhdpi": "static/splash/xhdpi.png", // 720x1280
"xxhdpi": "static/splash/xxhdpi.png", // 1080x1920
"xxxhdpi": "static/splash/xxxhdpi.png" // 1440x2560
},
"ios": {
"iphone": {
"640x960": "static/splash/640x960.png", // iPhone 4/4s
"640x1136": "static/splash/640x1136.png", // iPhone 5/5s/SE
"750x1334": "static/splash/750x1334.png", // iPhone 6/7/8
"1125x2436": "static/splash/1125x2436.png", // iPhone X/XS
"1242x2688": "static/splash/1242x2688.png" // iPhone XS Max
}
}
}
App.vue 是整个uni-app应用的根组件,它承担着三大核心职责:
App.vue 执行流程图:
<template>
<!--
App.vue的template通常为空
页面内容由pages.json中配置的路由决定
这里可以放置全局的弹窗、通知等组件
-->
<view>
<!-- 全局加载提示 -->
<view v-if="globalLoading" class="global-loading">
<view class="loading-spinner"></view>
<text class="loading-text">加载中...</text>
</view>
<!-- 全局通知组件 -->
<view v-if="globalMessage.show" class="global-message" :class="globalMessage.type">
<text>{{ globalMessage.content }}</text>
</view>
<!--
页面内容会自动渲染在这里
由uni-app框架根据pages.json配置决定
-->
</view>
</template>
<script>
// 引入工具函数
import { checkUpdate, getSystemInfo } from '@/utils/system.js'
import { checkLogin, getUserInfo } from '@/utils/auth.js'
import { initRequest } from '@/utils/request.js'
export default {
// ==================== 应用生命周期 ====================
/**
* 应用初始化时触发 - 全局只触发一次
* @param {Object} options 启动参数
*/
onLaunch(options) {
console.log('App Launch - 应用初始化', options)
// 1. 初始化全局数据
this.initGlobalData()
// 2. 获取系统信息
this.getSystemInfo()
// 3. 检查登录状态
this.checkAuthStatus()
// 4. 初始化网络请求配置
this.initNetwork()
// 5. 处理启动参数
this.handleLaunchOptions(options)
// 6. 初始化第三方服务
this.initThirdPartyServices()
console.log('应用初始化完成')
},
/**
* 应用显示到前台时触发
* @param {Object} options 参数
*/
onShow(options) {
console.log('App Show - 应用显示', options)
// 1. 检查应用更新
this.checkAppUpdate()
// 2. 恢复用户会话
this.restoreUserSession()
// 3. 刷新关键数据
this.refreshCriticalData()
// 4. 处理场景值(小程序)
if (options.scene) {
this.handleScene(options.scene, options.query)
}
// 5. 统计应用活跃
this.trackAppActive()
},
/**
* 应用隐藏到后台时触发
*/
onHide() {
console.log('App Hide - 应用隐藏')
// 1. 保存应用状态
this.saveApplicationState()
// 2. 暂停媒体播放
this.pauseMediaPlayback()
// 3. 清理敏感信息
this.clearSensitiveData()
// 4. 停止后台任务
this.stopBackgroundTasks()
// 5. 上报统计信息
this.reportUsageStatistics()
},
/**
* 应用发生脚本错误时触发
* @param {Error} error 错误对象
*/
onError(error) {
console.error('App Error - 应用错误', error)
// 1. 错误信息上报
this.reportError(error)
// 2. 显示友好错误提示
this.showErrorToast('应用出现了一些问题,请稍后重试')
// 3. 记录错误日志
this.logError(error)
},
/**
* 页面不存在时触发
* @param {Object} res 页面信息
*/
onPageNotFound(res) {
console.warn('Page Not Found - 页面不存在', res)
// 1. 重定向到404页面
uni.redirectTo({
url: '/pages/error/404?path=' + encodeURIComponent(res.path)
})
// 2. 上报页面丢失统计
this.reportPageNotFound(res)
},
// ==================== 数据定义 ====================
data() {
return {
// 全局加载状态
globalLoading: false,
// 全局消息通知
globalMessage: {
show: false,
content: '',
type: 'info' // info/success/warning/error
},
// 全局数据存储
globalData: {
// 系统信息
systemInfo: null,
// 用户信息
userInfo: null,
token: null,
// 应用设置
settings: {
theme: 'light',
language: 'zh-CN',
notification: true
},
// 业务数据缓存
cache: {
products: null,
categories: null,
userProfile: null
},
// 应用状态
status: {
isConnected: true, // 网络连接状态
isBackground: false, // 是否在后台
lastActiveTime: null // 最后活跃时间
}
}
}
},
// ==================== 方法定义 ====================
methods: {
// ========== 初始化相关方法 ==========
/**
* 初始化全局数据
*/
initGlobalData() {
console.log('初始化全局数据')
// 从缓存加载用户设置
const settings = uni.getStorageSync('app_settings')
if (settings) {
this.globalData.settings = { ...this.globalData.settings, ...settings }
}
// 从缓存加载用户信息
const userInfo = uni.getStorageSync('user_info')
if (userInfo) {
this.globalData.userInfo = userInfo
}
// 从缓存加载token
const token = uni.getStorageSync('user_token')
if (token) {
this.globalData.token = token
}
},
/**
* 获取系统信息
*/
async getSystemInfo() {
try {
const systemInfo = await getSystemInfo()
this.globalData.systemInfo = systemInfo
console.log('系统信息:', systemInfo)
// 根据系统信息调整UI
this.adjustUIForSystem(systemInfo)
} catch (error) {
console.error('获取系统信息失败:', error)
}
},
/**
* 检查认证状态
*/
async checkAuthStatus() {
const isLoggedIn = await checkLogin()
if (!isLoggedIn) {
// 未登录,可以跳转到登录页
// uni.redirectTo({ url: '/pages/login/login' })
console.log('用户未登录')
} else {
// 已登录,获取用户信息
await this.getUserInfo()
}
},
/**
* 初始化网络请求配置
*/
initNetwork() {
initRequest({
baseURL: process.env.VUE_APP_API_BASE,
timeout: 10000,
onRequest: (config) => {
// 请求拦截器
if (this.globalData.token) {
config.header['Authorization'] = `Bearer ${this.globalData.token}`
}
return config
},
onResponse: (response) => {
// 响应拦截器
return response
},
onError: (error) => {
// 错误处理
this.handleRequestError(error)
}
})
},
// ========== 显示/隐藏相关方法 ==========
/**
* 检查应用更新
*/
async checkAppUpdate() {
// #ifdef APP-PLUS
try {
const updateManager = uni.getUpdateManager()
updateManager.onCheckForUpdate((res) => {
console.log('检查更新结果:', res.hasUpdate)
})
updateManager.onUpdateReady(() => {
uni.showModal({
title: '更新提示',
content: '新版本已经准备好,是否重启应用?',
success: (res) => {
if (res.confirm) {
updateManager.applyUpdate()
}
}
})
})
updateManager.onUpdateFailed(() => {
uni.showToast({
title: '更新失败',
icon: 'none'
})
})
} catch (error) {
console.error('检查更新失败:', error)
}
// #endif
},
/**
* 恢复用户会话
*/
async restoreUserSession() {
// 检查token是否过期
if (this.globalData.token) {
const isValid = await this.validateToken(this.globalData.token)
if (!isValid) {
// token过期,重新登录
this.globalData.token = null
this.globalData.userInfo = null
uni.removeStorageSync('user_token')
uni.removeStorageSync('user_info')
}
}
},
// ========== 工具方法 ==========
/**
* 显示全局加载提示
*/
showLoading(message = '加载中...') {
this.globalLoading = true
// 可以在这里添加自定义加载UI
},
/**
* 隐藏全局加载提示
*/
hideLoading() {
this.globalLoading = false
},
/**
* 显示全局消息提示
*/
showMessage(content, type = 'info', duration = 3000) {
this.globalMessage = {
show: true,
content,
type
}
// 自动隐藏
setTimeout(() => {
this.globalMessage.show = false
}, duration)
},
/**
* 处理网络请求错误
*/
handleRequestError(error) {
console.error('网络请求错误:', error)
const { statusCode, errMsg } = error
switch (statusCode) {
case 401:
this.showMessage('登录已过期,请重新登录', 'error')
this.logout()
break
case 403:
this.showMessage('没有权限访问该资源', 'error')
break
case 404:
this.showMessage('请求的资源不存在', 'error')
break
case 500:
this.showMessage('服务器内部错误', 'error')
break
default:
this.showMessage('网络请求失败,请检查网络连接', 'error')
}
},
/**
* 用户登出
*/
logout() {
// 清理用户数据
this.globalData.userInfo = null
this.globalData.token = null
// 清理缓存
uni.removeStorageSync('user_token')
uni.removeStorageSync('user_info')
// 跳转到登录页
uni.redirectTo({
url: '/pages/login/login'
})
},
// ========== 其他辅助方法 ==========
/**
* 根据系统信息调整UI
*/
adjustUIForSystem(systemInfo) {
// 处理刘海屏、安全区域等
const { platform, screenWidth, screenHeight, statusBarHeight } = systemInfo
// 设置全局CSS变量
if (platform === 'ios') {
document.documentElement.style.setProperty('--status-bar-height', `${statusBarHeight}px`)
document.documentElement.style.setProperty('--safe-area-inset-bottom', '34px')
} else {
document.documentElement.style.setProperty('--status-bar-height', `${statusBarHeight}px`)
document.documentElement.style.setProperty('--safe-area-inset-bottom', '0px')
}
},
/**
* 验证token有效性
*/
async validateToken(token) {
try {
// 调用验证接口
const response = await this.$http.post('/auth/validate', { token })
return response.data.valid
} catch (error) {
return false
}
},
/**
* 获取用户信息
*/
async getUserInfo() {
try {
const userInfo = await getUserInfo()
this.globalData.userInfo = userInfo
uni.setStorageSync('user_info', userInfo)
} catch (error) {
console.error('获取用户信息失败:', error)
}
},
/**
* 处理启动参数
*/
handleLaunchOptions(options) {
console.log('处理启动参数:', options)
// 处理分享链接、推送消息等场景
if (options.query) {
this.handleDeepLink(options.query)
}
// 处理场景值(小程序)
if (options.scene) {
this.handleScene(options.scene, options.query)
}
},
/**
* 处理深度链接
*/
handleDeepLink(query) {
// 解析URL参数,跳转到对应页面
if (query.page === 'product' && query.id) {
uni.navigateTo({
url: `/pages/product/detail?id=${query.id}`
})
}
},
/**
* 处理场景值
*/
handleScene(scene, query) {
console.log('处理场景值:', scene, query)
// 记录场景统计
this.trackScene(scene)
},
/**
* 初始化第三方服务
*/
initThirdPartyServices() {
// 初始化统计SDK
this.initAnalytics()
// 初始化推送服务
this.initPushService()
// 初始化性能监控
this.initPerformanceMonitor()
},
/**
* 错误上报
*/
reportError(error) {
// 上报到错误监控平台
console.log('上报错误:', error)
}
},
// ==================== 生命周期结束 ====================
}
</script>
<style>
/* ==================== 全局样式重置 ==================== */
/* 页面基础样式 */
page {
background-color: #f8f8f8;
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica,
'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei',
SimSun, sans-serif;
font-size: 28rpx;
color: #333333;
line-height: 1.6;
}
/* 安全区域适配 */
.safe-area-inset-bottom {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
.safe-area-inset-top {
padding-top: constant(safe-area-inset-top);
padding-top: env(safe-area-inset-top);
}
/* ==================== 全局工具类 ==================== */
/* 文字对齐 */
.text-left { text-align: left; }
.text-center { text-align: center; }
.text-right { text-align: right; }
/* 文字颜色 */
.text-primary { color: #007AFF; }
.text-success { color: #4CD964; }
.text-warning { color: #FF9500; }
.text-error { color: #FF3B30; }
.text-muted { color: #8E8E93; }
/* 背景颜色 */
.bg-white { background-color: #FFFFFF; }
.bg-light { background-color: #F8F8F8; }
.bg-primary { background-color: #007AFF; }
/* 边距工具 */
.m-10 { margin: 10rpx; }
.p-10 { padding: 10rpx; }
.mt-10 { margin-top: 10rpx; }
.mb-10 { margin-bottom: 10rpx; }
/* 布局工具 */
.flex { display: flex; }
.flex-column { flex-direction: column; }
.flex-center {
display: flex;
align-items: center;
justify-content: center;
}
.flex-between {
display: flex;
align-items: center;
justify-content: space-between;
}
/* ==================== 全局组件样式 ==================== */
/* 全局加载样式 */
.global-loading {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 9999;
}
.loading-spinner {
width: 60rpx;
height: 60rpx;
border: 4rpx solid #FFFFFF;
border-top: 4rpx solid #007AFF;
border-radius: 50%;
animation: spin 1s linear infinite;
}
.loading-text {
color: #FFFFFF;
font-size: 28rpx;
margin-top: 20rpx;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* 全局消息样式 */
.global-message {
position: fixed;
top: 100rpx;
left: 50%;
transform: translateX(-50%);
padding: 20rpx 40rpx;
border-radius: 10rpx;
color: #FFFFFF;
font-size: 28rpx;
z-index: 9998;
max-width: 80%;
text-align: center;
}
.global-message.info {
background-color: #007AFF;
}
.global-message.success {
background-color: #4CD964;
}
.global-message.warning {
background-color: #FF9500;
}
.global-message.error {
background-color: #FF3B30;
}
/* ==================== 自定义全局样式 ==================== */
/* 容器样式 */
.container {
padding: 30rpx;
min-height: 100vh;
box-sizing: border-box;
}
.container-safe {
padding: 30rpx;
padding-bottom: calc(30rpx + constant(safe-area-inset-bottom));
padding-bottom: calc(30rpx + env(safe-area-inset-bottom));
min-height: 100vh;
box-sizing: border-box;
}
/* 卡片样式 */
.card {
background-color: #FFFFFF;
border-radius: 20rpx;
padding: 30rpx;
margin-bottom: 20rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
}
/* 按钮样式重置 */
uni-button[type=primary] {
background-color: #007AFF !important;
border-color: #007AFF !important;
}
uni-button[type=default] {
background-color: #FFFFFF !important;
border-color: #E5E5E5 !important;
color: #333333 !important;
}
/* 输入框样式重置 */
uni-input {
font-size: 28rpx !important;
}
/* ==================== 响应式设计 ==================== */
/* 平板适配 */
@media (min-width: 768px) {
.container {
max-width: 750px;
margin: 0 auto;
}
}
/* PC端适配 */
@media (min-width: 1200px) {
.container {
max-width: 1000px;
}
}
</style>
uni-app的生命周期分为应用生命周期和页面生命周期两个层次:
应用与页面生命周期关系图:
| 生命周期 | 触发时机 | 执行次数 | 常用场景 |
|---|---|---|---|
onLaunch | 应用初始化 | 1次 | 初始化全局数据、获取设备信息 |
onShow | 应用显示到前台 | 多次 | 检查更新、恢复会话、刷新数据 |
onHide | 应用隐藏到后台 | 多次 | 保存状态、暂停任务、清理数据 |
onError | 脚本错误 | 不确定 | 错误上报、友好提示 |
onPageNotFound | 页面不存在 | 不确定 | 404重定向、统计上报 |
| 生命周期 | 触发时机 | 执行次数 | 常用场景 |
|---|---|---|---|
onLoad | 页面加载 | 1次 | 接收参数、初始化数据 |
onShow | 页面显示 | 多次 | 刷新数据、恢复状态 |
onReady | 页面渲染完成 | 1次 | 操作DOM、初始化图表 |
onHide | 页面隐藏 | 多次 | 保存状态、暂停视频 |
onUnload | 页面卸载 | 1次 | 清理资源、取消请求 |
onPullDownRefresh | 下拉刷新 | 多次 | 刷新列表数据 |
onReachBottom | 上拉触底 | 多次 | 加载更多数据 |
onPageScroll | 页面滚动 | 多次 | 吸顶效果、隐藏导航 |
onShareAppMessage | 用户分享 | 多次 | 自定义分享内容 |
在App.vue中管理全局数据时,推荐使用以下模式:
// 在App.vue中
export default {
data() {
return {
globalData: {
// 用户相关
user: null,
token: null,
// 系统相关
systemInfo: null,
networkType: 'wifi',
// 应用状态
settings: {},
cache: {}
}
}
},
// 提供全局方法
methods: {
// 设置全局数据
setGlobalData(key, value) {
this.globalData[key] = value
// 触发数据变化通知
this.$emit('globalDataChange', { key, value })
},
// 获取全局数据
getGlobalData(key) {
return this.globalData[key]
},
// 监听全局数据变化
watchGlobalData(key, callback) {
this.$on('globalDataChange', ({ key: changedKey, value }) => {
if (changedKey === key) {
callback(value)
}
})
}
}
}
// 在页面中使用
// const app = getApp()
// app.setGlobalData('user', userInfo)
// app.watchGlobalData('user', (newUser) => { ... })
排查步骤:
检查
pages.json 中页面路径配置是否正确确认页面文件是否存在且路径正确检查页面组件中的语法错误查看网络请求是否被阻塞
解决方案:
// 在App.vue中添加页面不存在处理
onPageNotFound(res) {
console.error('页面不存在:', res)
// 跳转到错误页面
uni.redirectTo({
url: '/pages/error/404?path=' + encodeURIComponent(res.path)
})
// 或者跳转到首页
// uni.reLaunch({ url: '/pages/index/index' })
}
原因: 在App.vue中定义了过于宽泛的选择器
解决方案:
<style>
/* 不推荐 */
view {
color: red;
}
button {
background: blue;
}
/* 推荐 */
/* 使用类名限制作用范围 */
.global-view {
color: red;
}
.global-button {
background: blue;
}
/* 或者使用页面独有的样式文件 */
</style>
<style scoped>
/* 使用scoped确保样式只影响当前组件 */
.page-container {
padding: 20rpx;
}
</style>
排查步骤:
检查
pages.json 中
tabBar.list 配置确认图标文件路径是否正确检查页面路径是否与
pagePath 一致查看控制台是否有错误信息
解决方案:
{
"tabBar": {
"list": [
{
"pagePath": "pages/index/index",
"iconPath": "/static/tabbar/home.png", // 使用绝对路径
"selectedIconPath": "/static/tabbar/home-active.png",
"text": "首页"
}
]
}
}
{
"globalStyle": {
"renderingMode": "seperated", // 样式渲染模式
"leftWindow": false, // 关闭左窗口
"topWindow": false, // 关闭顶窗口
"rightWindow": false // 关闭右窗口
},
"app-plus": {
"optimization": {
"subPackages": true // 开启分包优化
}
},
"h5": {
"optimization": {
"treeShaking": {
"enable": true // 开启摇树优化
}
}
}
}
// 使用条件编译减少代码体积
// #ifdef H5
console.log('H5平台特定代码')
// #endif
// #ifdef MP-WEIXIN
console.log('微信小程序特定代码')
// #endif
// 合理使用异步加载
onLoad() {
// 延迟加载不重要资源
setTimeout(() => {
this.loadSecondaryData()
}, 1000)
}
// 使用图片懒加载
<image lazy-load src="{{imageUrl}}"></image>
、、、、、、
// 在关键位置添加日志
onLaunch(options) {
console.group('App Launch 调试信息')
console.log('启动参数:', options)
console.log('应用版本:', this.versionName)
console.log('设备信息:', this.globalData.systemInfo)
console.groupEnd()
}
// 在页面中使用
onLoad(query) {
console.log('页面加载,参数:', query)
console.table(query) // 以表格形式输出
}
通过以上内容我们已经掌握了uni-app项目结构和配置文件的各个方面:
src/
├── api/ # 接口层 - 按模块划分
├── assets/ # 静态资源 - 图片、字体等
├── components/ # 组件库 - 基础/业务组件分离
├── pages/ # 页面 - 按功能模块组织
├── store/ # 状态管理 - Vuex模块化
├── utils/ # 工具函数 - 功能分类
└── styles/ # 样式文件 - 变量、混合、重置
// config/index.js - 统一配置管理
export default {
// 应用配置
app: {
name: '商城',
version: '1.0.0'
},
// API配置
api: {
baseURL: process.env.VUE_APP_API_BASE,
timeout: 10000
},
// 存储配置
storage: {
prefix: 'sm_',
timeout: 7 * 24 * 60 * 60 * 1000 // 7天
}
}
// utils/errorHandler.js - 统一错误处理
class ErrorHandler {
// 应用错误
static appError(error) {
console.error('应用错误:', error)
// 上报到监控平台
}
// 网络错误
static networkError(error) {
console.error('网络错误:', error)
// 显示网络错误提示
}
// 业务错误
static businessError(error) {
console.error('业务错误:', error)
// 显示业务错误提示
}
}
export default ErrorHandler
理论学得再多,不如动手实践。遇到问题时多查阅官方文档和社区
如果觉得这篇文章对你有帮助,请一键三连(点赞、关注、收藏)!