uni-app 项目结构与配置

章节概述

本章节将详细介绍 uni-app 项目的目录结构、核心配置文件的作用和配置方法,以及页面生命周期的理解和应用。通过本章节的学习,您将掌握 uni-app 项目的组织方式,能够正确配置项目参数,理解页面生命周期的各个阶段,为后续的开发工作打下坚实的基础。

核心知识点

1. 项目目录结构

基本目录结构

uni-app 项目的基本目录结构如下:

project-name/
├── components/         # 组件目录
├── pages/             # 页面目录
│   ├── index/         # 首页
│   └── detail/        # 详情页
├── static/            # 静态资源目录
├── uni_modules/       # uni 模块目录
├── unpackage/         # 打包输出目录
├── App.vue            # 应用入口文件
├── main.js            # 应用入口脚本
├── manifest.json      # 应用配置文件
├── pages.json         # 页面路由配置文件
└── uni.scss           # 全局样式文件

目录功能说明

目录/文件 功能说明
components/ 存放可复用的组件,支持全局组件和局部组件
pages/ 存放应用的页面,每个页面是一个目录,包含.vue文件
static/ 存放静态资源,如图片、字体等,不会被编译
uni_modules/ 存放 uni-app 官方或第三方模块
unpackage/ 存放编译打包后的文件,不同平台有不同的子目录
App.vue 应用的根组件,整个应用的入口页面
main.js 应用的入口脚本文件,初始化Vue实例
manifest.json 应用的配置文件,包含应用名称、图标、权限等
pages.json 页面路由配置文件,定义页面路径、导航栏样式等
uni.scss 全局样式文件,可定义全局变量和样式

2. 配置文件说明

manifest.json

manifest.json 是 uni-app 应用的全局配置文件,用于配置应用的基本信息、权限、平台特性等。

主要配置项
  • 基本信息:应用名称、AppID、版本号等
  • 权限配置:如定位、相机、录音等权限
  • 平台配置:针对不同平台的特定配置
  • uni-app 配置:如是否开启 uni 统计等
配置示例
{
  "name": "uni-app-demo",
  "appid": "__UNI__XXXXXXXX",
  "description": "uni-app 示例应用",
  "versionName": "1.0.0",
  "versionCode": "1",
  "transformPx": true,
  "uniStatistics": {
    "enable": true
  },
  "app-plus": {
    "usingComponents": true,
    "nvueStyleCompiler": "uni-app",
    "compilerVersion": 3,
    "splashscreen": {
      "alwaysShowBeforeRender": true,
      "waiting": true,
      "autoclose": true,
      "delay": 0
    },
    "permissions": {
      "location": {
        "desc": "用于获取当前位置信息"
      },
      "camera": {
        "desc": "用于拍摄照片"
      }
    }
  },
  "mp-weixin": {
    "appid": "wx1234567890",
    "setting": {
      "urlCheck": false
    },
    "usingComponents": true
  }
}

pages.json

pages.json 是 uni-app 的页面路由配置文件,用于配置页面路径、导航栏样式、标签栏等。

主要配置项
  • pages:定义页面路径和页面样式
  • globalStyle:定义全局样式,如导航栏、窗口背景色等
  • tabBar:配置应用的标签栏
  • subPackages:配置分包加载
  • preloadRule:配置页面预加载规则
配置示例
{
  "pages": [
    {
      "path": "pages/index/index",
      "style": {
        "navigationBarTitleText": "首页",
        "enablePullDownRefresh": true
      }
    },
    {
      "path": "pages/detail/detail",
      "style": {
        "navigationBarTitleText": "详情页",
        "navigationBarBackgroundColor": "#007AFF"
      }
    }
  ],
  "globalStyle": {
    "navigationBarTextStyle": "black",
    "navigationBarTitleText": "uni-app",
    "navigationBarBackgroundColor": "#F8F8F8",
    "backgroundColor": "#F8F8F8"
  },
  "tabBar": {
    "color": "#999",
    "selectedColor": "#007AFF",
    "backgroundColor": "#fff",
    "borderStyle": "black",
    "list": [
      {
        "pagePath": "pages/index/index",
        "text": "首页",
        "iconPath": "static/icon/home.png",
        "selectedIconPath": "static/icon/home-active.png"
      },
      {
        "pagePath": "pages/mine/mine",
        "text": "我的",
        "iconPath": "static/icon/mine.png",
        "selectedIconPath": "static/icon/mine-active.png"
      }
    ]
  }
}

App.vue

App.vue 是 uni-app 的根组件,整个应用的入口页面。

主要功能
  • 定义全局样式
  • 处理应用级别的生命周期
  • 全局数据和方法的定义
示例代码
<template>
  <view class="app">
    <router-view />
  </view>
</template>

<script>
export default {
  onLaunch() {
    // 应用启动时执行
    console.log('App Launch')
  },
  onShow() {
    // 应用显示时执行
    console.log('App Show')
  },
  onHide() {
    // 应用隐藏时执行
    console.log('App Hide')
  },
  globalData: {
    userInfo: null
  }
}
</script>

<style>
/* 全局样式 */
.app {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  padding: 0;
  margin: 0;
}
</style>

main.js

main.js 是 uni-app 的入口脚本文件,用于初始化 Vue 实例。

主要功能
  • 导入 Vue 和 App 组件
  • 配置 Vue 实例
  • 挂载应用
  • 导入全局插件和工具
示例代码
import Vue from 'vue'
import App from './App.vue'

// 导入全局插件
import uView from 'uview-ui'
Vue.use(uView)

// 导入全局工具
import utils from './utils/index.js'
Vue.prototype.$utils = utils

// 配置 Vue 实例
Vue.config.productionTip = false

App.mpType = 'app'

const app = new Vue({
  ...App
})
app.$mount()

3. 页面生命周期

应用生命周期

uni-app 应用有以下生命周期函数:

生命周期函数 说明
onLaunch 应用初始化完成时触发,全局只触发一次
onShow 应用启动或从后台进入前台显示时触发
onHide 应用从前台进入后台时触发
onError 应用出错时触发
onUniNViewMessage 对 nvue 页面发送的数据进行监听

页面生命周期

uni-app 页面有以下生命周期函数:

生命周期函数 说明 平台支持
onLoad 页面加载时触发,参数为上个页面传递的数据 全平台
onShow 页面显示时触发 全平台
onReady 页面初次渲染完成时触发 全平台
onHide 页面隐藏时触发 全平台
onUnload 页面卸载时触发 全平台
onPullDownRefresh 下拉刷新时触发 全平台
onReachBottom 上拉触底时触发 全平台
onShareAppMessage 用户点击分享时触发 微信小程序、QQ小程序
onPageScroll 页面滚动时触发 全平台
onTabItemTap 点击 tabBar 时触发 微信小程序、QQ小程序、App

生命周期执行顺序

页面生命周期的执行顺序如下:

  1. onLoad → 2. onShow → 3. onReady → 4. onHide → 5. onUnload

实用案例分析

配置多端适配参数

案例目标

配置 uni-app 项目的多端适配参数,确保应用在不同平台上都能正常显示和运行。

实现步骤

  1. 配置 manifest.json

    • 配置应用基本信息
    • 配置各平台特定参数
    • 配置权限信息
  2. 配置 pages.json

    • 配置页面路径和样式
    • 配置全局样式
    • 配置标签栏
  3. 配置多端样式

    • 使用条件编译处理平台差异
    • 配置响应式布局

具体实现

1. 配置 manifest.json
{
  "name": "multi-platform-app",
  "appid": "__UNI__XXXXXXXX",
  "versionName": "1.0.0",
  "versionCode": "1",
  "transformPx": true,
  "app-plus": {
    "usingComponents": true,
    "compilerVersion": 3,
    "splashscreen": {
      "alwaysShowBeforeRender": true,
      "autoclose": true
    }
  },
  "mp-weixin": {
    "appid": "wx1234567890",
    "setting": {
      "urlCheck": false
    },
    "usingComponents": true
  },
  "mp-alipay": {
    "usingComponents": true
  },
  "mp-baidu": {
    "usingComponents": true
  },
  "h5": {
    "router": {
      "mode": "hash"
    }
  }
}
2. 配置 pages.json
{
  "pages": [
    {
      "path": "pages/index/index",
      "style": {
        "navigationBarTitleText": "首页",
        "enablePullDownRefresh": true,
        "h5": {
          "pullToRefresh": {
            "color": "#007AFF"
          }
        }
      }
    }
  ],
  "globalStyle": {
    "navigationBarTextStyle": "black",
    "navigationBarTitleText": "多端适配示例",
    "navigationBarBackgroundColor": "#F8F8F8",
    "backgroundColor": "#F8F8F8"
  },
  "tabBar": {
    "color": "#999",
    "selectedColor": "#007AFF",
    "backgroundColor": "#fff",
    "borderStyle": "black",
    "list": [
      {
        "pagePath": "pages/index/index",
        "text": "首页",
        "iconPath": "static/icon/home.png",
        "selectedIconPath": "static/icon/home-active.png"
      },
      {
        "pagePath": "pages/mine/mine",
        "text": "我的",
        "iconPath": "static/icon/mine.png",
        "selectedIconPath": "static/icon/mine-active.png"
      }
    ]
  }
}
3. 使用条件编译
<template>
  <view class="container">
    <view class="content">
      <text>多端适配示例</text>
      <!-- #ifdef MP-WEIXIN -->
      <view class="weixin-only">微信小程序特有内容</view>
      <!-- #endif -->
      <!-- #ifdef APP-PLUS -->
      <view class="app-only">App特有内容</view>
      <!-- #endif -->
      <!-- #ifdef H5 -->
      <view class="h5-only">H5特有内容</view>
      <!-- #endif -->
    </view>
  </view>
</template>

<script>
export default {
  onLoad() {
    console.log('页面加载')
    // 条件编译示例
    // #ifdef MP-WEIXIN
    console.log('微信小程序端')
    // #endif
    // #ifdef APP-PLUS
    console.log('App端')
    // #endif
  }
}
</script>

<style>
.container {
  padding: 20rpx;
}

.content {
  text-align: center;
}

/* 条件编译样式 */
/* #ifdef MP-WEIXIN */
.weixin-only {
  color: green;
  margin-top: 20rpx;
}
/* #endif */

/* #ifdef APP-PLUS */
.app-only {
  color: blue;
  margin-top: 20rpx;
}
/* #endif */

/* #ifdef H5 */
.h5-only {
  color: red;
  margin-top: 20rpx;
}
/* #endif */
</style>

运行效果

  • 微信小程序:显示绿色的"微信小程序特有内容"
  • App:显示蓝色的"App特有内容"
  • H5:显示红色的"H5特有内容"

代码示例

页面生命周期示例

<template>
  <view class="life-cycle-demo">
    <view class="title">生命周期演示</view>
    <view class="log-list">
      <view v-for="(log, index) in logList" :key="index" class="log-item">
        {{ log }}
      </view>
    </view>
    <button @tap="navigateToDetail" class="nav-btn">跳转到详情页</button>
  </view>
</template>

<script>
export default {
  data() {
    return {
      logList: []
    }
  },
  onLoad() {
    this.addLog('onLoad: 页面加载')
  },
  onShow() {
    this.addLog('onShow: 页面显示')
  },
  onReady() {
    this.addLog('onReady: 页面初次渲染完成')
  },
  onHide() {
    this.addLog('onHide: 页面隐藏')
  },
  onUnload() {
    this.addLog('onUnload: 页面卸载')
  },
  onPullDownRefresh() {
    this.addLog('onPullDownRefresh: 下拉刷新')
    setTimeout(() => {
      uni.stopPullDownRefresh()
    }, 1000)
  },
  onReachBottom() {
    this.addLog('onReachBottom: 上拉触底')
  },
  methods: {
    addLog(log) {
      const time = new Date().toLocaleTimeString()
      this.logList.push(`${time} - ${log}`)
    },
    navigateToDetail() {
      uni.navigateTo({
        url: '/pages/detail/detail'
      })
    }
  }
}
</script>

<style>
.life-cycle-demo {
  padding: 20rpx;
}

.title {
  font-size: 32rpx;
  font-weight: bold;
  text-align: center;
  margin-bottom: 30rpx;
}

.log-list {
  background-color: #f5f5f5;
  padding: 20rpx;
  border-radius: 10rpx;
  max-height: 500rpx;
  overflow-y: auto;
}

.log-item {
  font-size: 24rpx;
  margin-bottom: 10rpx;
  color: #666;
}

.nav-btn {
  margin-top: 30rpx;
  padding: 20rpx;
  background-color: #007AFF;
  color: white;
  border-radius: 10rpx;
}
</style>

分包加载配置示例

{
  "pages": [
    {
      "path": "pages/index/index",
      "style": {
        "navigationBarTitleText": "首页"
      }
    },
    {
      "path": "pages/mine/mine",
      "style": {
        "navigationBarTitleText": "我的"
      }
    }
  ],
  "subPackages": [
    {
      "root": "pagesA",
      "pages": [
        {
          "path": "list/list",
          "style": {
            "navigationBarTitleText": "列表页"
          }
        },
        {
          "path": "detail/detail",
          "style": {
            "navigationBarTitleText": "详情页"
          }
        }
      ]
    },
    {
      "root": "pagesB",
      "pages": [
        {
          "path": "settings/settings",
          "style": {
            "navigationBarTitleText": "设置页"
          }
        }
      ]
    }
  ],
  "preloadRule": {
    "pages/index/index": {
      "network": "all",
      "packages": ["pagesA"]
    }
  }
}

常见问题与解决方案

1. 页面路径配置错误

  • 问题:配置了页面路径但无法访问
  • 解决方案:检查 pages.json 中的路径配置是否正确,确保页面文件存在

2. 导航栏样式不生效

  • 问题:配置了导航栏样式但不生效
  • 解决方案:检查 pages.json 中的样式配置,确保配置格式正确

3. 权限配置不生效

  • 问题:配置了权限但应用无法获取权限
  • 解决方案:检查 manifest.json 中的权限配置,确保权限描述清晰

4. 生命周期函数不执行

  • 问题:页面生命周期函数不执行
  • 解决方案:检查生命周期函数名称是否正确,确保函数在正确的位置定义

5. 分包加载失败

  • 问题:配置了分包但加载失败
  • 解决方案:检查分包配置是否正确,确保分包大小不超过平台限制

学习总结

通过本章节的学习,您已经了解了:

  1. uni-app 项目的目录结构:各个目录和文件的作用和功能
  2. 核心配置文件的使用:manifest.json、pages.json、App.vue 和 main.js 的配置方法
  3. 页面生命周期:应用和页面的生命周期函数及其执行顺序
  4. 多端适配配置:如何配置多端适配参数,处理平台差异
  5. 分包加载:如何配置分包加载,优化应用性能

现在您已经掌握了 uni-app 项目的结构和配置方法,可以开始学习页面开发的基础知识了。下一章节将详细介绍 uni-app 的页面开发基础,包括页面创建、导航跳转和参数传递等内容。

« 上一篇 uni-app 简介与环境搭建 下一篇 » uni-app 页面开发基础