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 |
生命周期执行顺序
页面生命周期的执行顺序如下:
- onLoad → 2. onShow → 3. onReady → 4. onHide → 5. onUnload
实用案例分析
配置多端适配参数
案例目标
配置 uni-app 项目的多端适配参数,确保应用在不同平台上都能正常显示和运行。
实现步骤
配置 manifest.json
- 配置应用基本信息
- 配置各平台特定参数
- 配置权限信息
配置 pages.json
- 配置页面路径和样式
- 配置全局样式
- 配置标签栏
配置多端样式
- 使用条件编译处理平台差异
- 配置响应式布局
具体实现
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. 分包加载失败
- 问题:配置了分包但加载失败
- 解决方案:检查分包配置是否正确,确保分包大小不超过平台限制
学习总结
通过本章节的学习,您已经了解了:
- uni-app 项目的目录结构:各个目录和文件的作用和功能
- 核心配置文件的使用:manifest.json、pages.json、App.vue 和 main.js 的配置方法
- 页面生命周期:应用和页面的生命周期函数及其执行顺序
- 多端适配配置:如何配置多端适配参数,处理平台差异
- 分包加载:如何配置分包加载,优化应用性能
现在您已经掌握了 uni-app 项目的结构和配置方法,可以开始学习页面开发的基础知识了。下一章节将详细介绍 uni-app 的页面开发基础,包括页面创建、导航跳转和参数传递等内容。