《uni-app跨平台开发完全指南》- 02 - 项目结构与配置文件详解

  • 时间:2025-11-06 18:40 作者: 来源: 阅读:0
  • 扫一扫,手机访问
摘要:项目结构与配置文件 掌握uni-app项目结构就像学开车前先熟悉车内布局,看似繁琐却能让你在开发路上游刃有余。本文用大量图表和实战案例,帮你彻底搞懂uni-app项目的"五脏六腑"。 一、初识uni-app项目结构 1.1 项目结构图 当你创建第一个uni-app项目时,看到的目录结构可能是这样的: my-uni-app/ ├── pages/ # 页面文件

项目结构与配置文件

掌握uni-app项目结构就像学开车前先熟悉车内布局,看似繁琐却能让你在开发路上游刃有余。本文用大量图表和实战案例,帮你彻底搞懂uni-app项目的"五脏六腑"。

一、初识uni-app项目结构

1.1 项目结构图

当你创建第一个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/ │ │     │
│  │  └─────────────┘  └─────────────┘  └─────────────┘ │     │
│  └────────────────────────────────────────────────────┘     │
│                                                             │
└─────────────────────────────────────────────────────────────┘

1.2 目录职责

如果把目录结构比作一家公司,那么每个目录的作用如下:

pages/ - 各个部门办公室(每个页面都是独立部门) static/ - 公司仓库(存放不会变动的资产) components/ - 标准化工作台(可复用的工具和模板) uni_modules/ - 外包服务团队(第三方功能模块) App.vue - 总经理办公室(全局决策和管理) main.js - 公司大门(所有人进入公司的入口) manifest.json - 公司营业执照(应用身份证明) pages.json - 公司组织架构图(页面关系和样式规范)

1.3 项目目录结构设计

实战项目中,推荐的目录结构如下:


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 深度解析

2.1 pages.json 的作用机制

pages.json 是uni-app的路由中枢样式调度中心,它决定了:

页面路由关系 - 哪个路径对应哪个页面全局样式规范 - 导航栏、背景色等统一设置页面个性配置 - 每个页面的特殊样式需求底部导航管理 - TabBar的配置和交互

pages.json 配置流程图:

2.2 完整配置实例分析

下面以一个电商应用为例,完整 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"                   // 最低支持版本
      }
    }
  }
}

2.3 配置项解析

页面路由配置详细介绍

页面路径配置原理图:


┌─────────────────────────────────────────────────────────────┐
│                   页面路由配置原理                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  用户访问路径: /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配置如下:


{
  "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

3.1 manifest.json 的作用

manifest.json 是uni-app应用的身份证功能说明书,它定义了:

应用基本信息 - 名称、版本、描述等图标和启动图 - 各平台的图标和启动界面权限配置 - 应用需要的系统权限模块配置 - 使用的原生模块功能平台差异化配置 - 各平台的特定设置

manifest.json 配置架构图:

3.2 完整配置案例

下面是一个完整的 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
  }
}

3.3 关键配置详细解析

应用图标配置

应用图标是用户的第一印象,配置时需要注意尺寸,格式为png即可:

图标尺寸规范表:

平台设备类型尺寸用途备注
AndroidLDPI36x36低密度屏幕已较少使用
AndroidMDPI48x48中密度屏幕基准尺寸
AndroidHDPI72x72高密度屏幕常见尺寸
AndroidXHDPI96x96超高密度主流尺寸
AndroidXXHDPI144x144超超高密度高端设备
AndroidXXXHDPI192x192超超超高密度最新设备
iOSiPhone120x120iPhone @2xiPhone 6/7/8
iOSiPhone180x180iPhone @3xiPhone 6+/7+/8+
iOSiPad76x76iPad 1x非Retina iPad
iOSiPad152x152iPad @2xRetina 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 与生命周期管理

4.1 App.vue 的核心作用

App.vue 是整个uni-app应用的根组件,它承担着三大核心职责:

应用生命周期管理 - 控制应用的启动、显示、隐藏等全局样式定义 - 定义影响所有页面的基础样式全局数据存储 - 提供跨页面共享的数据存储

App.vue 执行流程图:

4.2 完整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>

4.3 生命周期详细介绍

uni-app的生命周期分为应用生命周期页面生命周期两个层次:

应用与页面生命周期关系图:

应用生命周期详细说明
生命周期触发时机执行次数常用场景
onLaunch应用初始化1次初始化全局数据、获取设备信息
onShow应用显示到前台多次检查更新、恢复会话、刷新数据
onHide应用隐藏到后台多次保存状态、暂停任务、清理数据
onError脚本错误不确定错误上报、友好提示
onPageNotFound页面不存在不确定404重定向、统计上报
页面生命周期详细说明
生命周期触发时机执行次数常用场景
onLoad页面加载1次接收参数、初始化数据
onShow页面显示多次刷新数据、恢复状态
onReady页面渲染完成1次操作DOM、初始化图表
onHide页面隐藏多次保存状态、暂停视频
onUnload页面卸载1次清理资源、取消请求
onPullDownRefresh下拉刷新多次刷新列表数据
onReachBottom上拉触底多次加载更多数据
onPageScroll页面滚动多次吸顶效果、隐藏导航
onShareAppMessage用户分享多次自定义分享内容

4.4 全局数据管理

在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) => { ... })

五、项目常见问题及解决办法

5.1 常见问题解决方案

问题1:页面白屏或加载失败

排查步骤:

检查 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' })
}
问题2:全局样式错乱,某个页面的样式影响了其他页面

原因: 在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>
问题3:TabBar不显示或显示异常

排查步骤:

检查 pages.json tabBar.list 配置确认图标文件路径是否正确检查页面路径是否与 pagePath 一致查看控制台是否有错误信息

解决方案:


{
  "tabBar": {
    "list": [
      {
        "pagePath": "pages/index/index",
        "iconPath": "/static/tabbar/home.png",      // 使用绝对路径
        "selectedIconPath": "/static/tabbar/home-active.png",
        "text": "首页"
      }
    ]
  }
}

5.2 性能优化

配置优化

{
  "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>

、、、、、、

5.3 调试技巧

使用console.log进行调试

// 在关键位置添加日志
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开发者工具
HBuilderX调试:使用内置调试器查看日志浏览器调试:H5平台可使用Chrome DevTools小程序调试:使用微信开发者工具App调试:使用真机调试和日志查看

六、总结

6.1 核心要点回顾

通过以上内容我们已经掌握了uni-app项目结构和配置文件的各个方面:

配置文件
pages.json:路由管理和样式配置中枢manifest.json:应用身份和功能配置中心App.vue:全局生命周期和数据管理
生命周期
应用生命周期:控制应用整体行为页面生命周期:管理单个页面状态数据流管理:全局数据和状态共享
目录结构规范

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

理论学得再多,不如动手实践。遇到问题时多查阅官方文档和社区

如果觉得这篇文章对你有帮助,请一键三连(点赞、关注、收藏)!

  • 全部评论(0)
最新发布的资讯信息
【系统环境|】web前端培训:6个常用的前端开发构建工具(2025-11-06 22:33)
【系统环境|】现代包管理器pnpm 、npm、yarn?(2025-11-06 22:32)
【系统环境|】一款无需写任何代码即可一键生成前后端代码的开源工具(2025-11-06 22:32)
【系统环境|】提示工程架构师教你借助Agentic AI提升社交媒体用户留存率(2025-11-06 22:31)
【系统环境|】电子元器件-逻辑器件篇:逻辑电平、CMOS逻辑、手册解读、逻辑电平转换,应用注意事项(2025-11-06 22:31)
【系统环境|】Linux基础-包管理工具yum和apt对比(2025-11-06 22:30)
【系统环境|】RPM包离线下载方法(2025-11-06 22:30)
【系统环境|】红帽linux系统与UOS命令对比(2025-11-06 22:29)
【系统环境|】从 MIB 到告警:手把手教你用 Prometheus 监控交换机端口(2025-11-06 22:29)
【系统环境|】GitLab 13.12发布,安全性、可用性和管道管理加强(2025-11-06 22:28)
手机二维码手机访问领取大礼包
返回顶部