uni-app多端跨平台开发从入门到企业级实战 读书笔记

1. 入门篇

1.1 uni-app 简介

1.1.1 什么是 uni-app

uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到 iOS、Android、H5、以及各种小程序(微信/支付宝/百度/头条/QQ/钉钉/淘宝)等多个平台。

1.1.2 uni-app 的优势

  • 开发效率高:一套代码多端运行,减少重复开发
  • 性能优异:底层使用原生渲染,性能接近原生应用
  • 生态丰富:集成了大量的 UI 组件和插件
  • 开发成本低:使用 Vue.js 语法,学习成本低
  • 跨平台能力强:支持 10+ 个平台

1.1.3 uni-app 的应用场景

  • 企业级移动应用
  • 电商应用
  • 内容类应用
  • 工具类应用
  • 小程序开发

1.2 开发环境搭建

1.2.1 安装 HBuilderX

HBuilderX 是 uni-app 官方推荐的开发工具,集成了代码编辑器、模拟器、打包工具等功能。

安装步骤

  1. 访问 HBuilderX 官网
  2. 下载对应操作系统的安装包
  3. 解压并安装 HBuilderX

1.2.2 创建 uni-app 项目

步骤

  1. 打开 HBuilderX
  2. 点击「文件」→「新建」→「项目」
  3. 选择「uni-app」项目类型
  4. 填写项目名称、存储位置
  5. 选择模板(默认模板、Hello uni-app、空项目等)
  6. 点击「创建」按钮

1.2.3 运行项目

运行到浏览器

  1. 点击工具栏的「运行」按钮
  2. 选择「运行到浏览器」→ 选择浏览器

运行到小程序模拟器

  1. 安装对应小程序的开发工具
  2. 在 HBuilderX 中点击「运行」→ 选择对应小程序

运行到手机

  1. 连接手机到电脑
  2. 开启 USB 调试模式
  3. 在 HBuilderX 中点击「运行」→ 选择「运行到 Android App 基座」

1.3 项目结构

1.3.1 基本目录结构

1
2
3
4
5
6
7
8
9
├── components/         # 组件目录
├── pages/ # 页面目录
├── static/ # 静态资源目录
├── unpackage/ # 打包输出目录
├── App.vue # 应用入口文件
├── main.js # 应用入口文件
├── manifest.json # 应用配置文件
├── pages.json # 页面配置文件
└── uni.scss # 全局样式文件

1.3.2 配置文件说明

  • manifest.json:配置应用名称、图标、权限等
  • pages.json:配置页面路由、导航栏、底部 tab 等
  • uni.scss:全局样式变量

2. 核心概念

2.1 页面生命周期

uni-app 的页面生命周期与 Vue 的生命周期有所不同,它结合了小程序的生命周期特点。

2.1.1 页面生命周期函数

函数名说明平台差异
onLoad页面加载时触发,只触发一次所有平台
onShow页面显示/切入前台时触发所有平台
onReady页面初次渲染完成时触发,只触发一次所有平台
onHide页面隐藏/切入后台时触发所有平台
onUnload页面卸载时触发所有平台
onPullDownRefresh下拉刷新时触发所有平台
onReachBottom上拉触底时触发所有平台
onShareAppMessage用户点击分享时触发微信小程序、QQ小程序
onPageScroll页面滚动时触发所有平台
onResize窗口尺寸变化时触发微信小程序、H5

2.2 组件

2.2.1 内置组件

uni-app 提供了丰富的内置组件,如 view、text、button、image 等,这些组件在各个平台都有良好的兼容性。

常用内置组件

  • view:视图容器,类似于 HTML 的 div
  • text:文本组件
  • button:按钮组件
  • image:图片组件
  • navigator:页面跳转组件
  • scroll-view:滚动视图组件
  • swiper:轮播图组件
  • picker:选择器组件
  • input:输入框组件

2.2.2 自定义组件

创建自定义组件

  1. 在 components 目录下创建组件目录
  2. 创建 .vue 文件,编写组件代码
  3. 在页面中引入并注册组件

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!-- components/my-component.vue -->
<template>
<view class="my-component">
<text>{{ title }}</text>
</view>
</template>

<script>
export default {
name: 'my-component',
props: {
title: {
type: String,
default: '默认标题'
}
},
data() {
return {};
}
};
</script>

<style scoped>
.my-component {
padding: 20rpx;
background-color: #f5f5f5;
}
</style>

使用组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<view>
<my-component title="自定义组件" />
</view>
</template>

<script>
import myComponent from '@/components/my-component.vue';

export default {
components: {
myComponent
}
};
</script>

2.3 API

uni-app 封装了各平台的原生 API,提供了统一的调用方式。

2.3.1 常用 API

  • 网络请求:uni.request()
  • 存储:uni.setStorageSync()、uni.getStorageSync()
  • 导航:uni.navigateTo()、uni.redirectTo()、uni.switchTab()
  • 界面:uni.showToast()、uni.showLoading()、uni.showModal()
  • 设备:uni.getSystemInfoSync()
  • 媒体:uni.chooseImage()、uni.uploadFile()

2.3.2 API 调用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 网络请求
uni.request({
url: 'https://api.example.com/data',
method: 'GET',
success: (res) => {
console.log(res.data);
},
fail: (err) => {
console.error(err);
}
});

// 存储数据
uni.setStorageSync('userInfo', { name: '张三', age: 20 });

// 获取存储数据
const userInfo = uni.getStorageSync('userInfo');

// 页面跳转
uni.navigateTo({
url: '/pages/detail/detail?id=1'
});

2.4 路由与页面跳转

2.4.1 路由配置

在 pages.json 中配置页面路由:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首页"
}
},
{
"path": "pages/detail/detail",
"style": {
"navigationBarTitleText": "详情页"
}
}
],
"tabBar": {
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "static/home.png",
"selectedIconPath": "static/home-active.png"
},
{
"pagePath": "pages/mine/mine",
"text": "我的",
"iconPath": "static/mine.png",
"selectedIconPath": "static/mine-active.png"
}
]
}
}

2.4.2 页面跳转方式

  • uni.navigateTo():保留当前页面,跳转到应用内的某个页面
  • uni.redirectTo():关闭当前页面,跳转到应用内的某个页面
  • uni.reLaunch():关闭所有页面,打开到应用内的某个页面
  • uni.switchTab():跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
  • uni.navigateBack():关闭当前页面,返回上一页面或多级页面

3. 组件与 UI

3.1 内置 UI 组件

3.1.1 uni-ui

uni-ui 是 DCloud 官方提供的一套 UI 组件库,适配多端,风格统一。

安装
在 HBuilderX 中点击「工具」→「插件安装」→ 搜索「uni-ui」并安装。

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<template>
<view>
<uni-badge text="12" type="error"></uni-badge>
<uni-button type="primary">按钮</uni-button>
</view>
</template>

<script>
import { uniBadge, uniButton } from '@dcloudio/uni-ui';

export default {
components: {
uniBadge,
uniButton
}
};
</script>

3.1.2 其他 UI 库

  • uView UI:基于 uni-app 的 UI 框架
  • ColorUI:鲜亮的高饱和色彩,专注视觉的小程序组件库
  • ThorUI:轻量级高性能 UI 组件库

3.2 自定义组件开发

3.2.1 组件通信

  • props/emit:父组件向子组件传递数据,子组件向父组件传递事件
  • $refs:父组件通过 ref 访问子组件实例
  • globalData:全局数据
  • Vuex:状态管理

3.2.2 组件生命周期

组件的生命周期与页面生命周期类似,但也有一些差异:

  • beforeCreate:组件实例创建前
  • created:组件实例创建后
  • beforeMount:组件挂载前
  • mounted:组件挂载后
  • beforeUpdate:组件更新前
  • updated:组件更新后
  • beforeDestroy:组件销毁前
  • destroyed:组件销毁后

3.3 组件封装最佳实践

  • 单一职责:一个组件只负责一个功能
  • 可配置性:通过 props 提供配置项
  • 事件传递:通过 emit 传递事件
  • 样式隔离:使用 scoped 或 CSS Modules
  • 文档完善:提供清晰的使用文档

4. 状态管理

4.1 Vuex

uni-app 内置了 Vuex,可以直接使用。

4.1.1 创建 store

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// store/index.js
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
state: {
userInfo: null,
token: ''
},
mutations: {
setUserInfo(state, userInfo) {
state.userInfo = userInfo;
},
setToken(state, token) {
state.token = token;
}
},
actions: {
login({ commit }, userInfo) {
// 模拟登录请求
return new Promise((resolve) => {
setTimeout(() => {
commit('setUserInfo', userInfo);
commit('setToken', 'mock-token');
resolve();
}, 1000);
});
}
},
getters: {
isLoggedIn: state => !!state.token
}
});

4.1.2 在 main.js 中引入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// main.js
import Vue from 'vue';
import App from './App.vue';
import store from './store';

Vue.config.productionTip = false;

App.mpType = 'app';

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

4.1.3 在组件中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<view>
<text v-if="isLoggedIn">{{ userInfo.name }}</text>
<button v-else @click="login">登录</button>
</view>
</template>

<script>
import { mapState, mapGetters, mapActions } from 'vuex';

export default {
computed: {
...mapState(['userInfo']),
...mapGetters(['isLoggedIn'])
},
methods: {
...mapActions(['login']),
handleLogin() {
this.login({ name: '张三', age: 20 });
}
}
};
</script>

4.2 Pinia

Pinia 是 Vue 3 推荐的状态管理库,也可以在 uni-app 中使用。

4.2.1 安装 Pinia

1
npm install pinia

4.2.2 创建 store

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// store/user.js
import { defineStore } from 'pinia';

export const useUserStore = defineStore('user', {
state: () => ({
userInfo: null,
token: ''
}),
getters: {
isLoggedIn: (state) => !!state.token
},
actions: {
login(userInfo) {
// 模拟登录请求
return new Promise((resolve) => {
setTimeout(() => {
this.userInfo = userInfo;
this.token = 'mock-token';
resolve();
}, 1000);
});
}
}
});

4.2.3 在 main.js 中引入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// main.js
import Vue from 'vue';
import App from './App.vue';
import { createPinia, PiniaVuePlugin } from 'pinia';

Vue.use(PiniaVuePlugin);
const pinia = createPinia();

Vue.config.productionTip = false;

App.mpType = 'app';

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

4.2.4 在组件中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<view>
<text v-if="userStore.isLoggedIn">{{ userStore.userInfo.name }}</text>
<button v-else @click="handleLogin">登录</button>
</view>
</template>

<script>
import { useUserStore } from '@/store/user';

export default {
data() {
return {
userStore: useUserStore()
};
},
methods: {
handleLogin() {
this.userStore.login({ name: '张三', age: 20 });
}
}
};
</script>

5. 网络请求

5.1 基础网络请求

5.1.1 使用 uni.request

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
uni.request({
url: 'https://api.example.com/data',
method: 'GET',
header: {
'Content-Type': 'application/json'
},
data: {
page: 1,
limit: 10
},
success: (res) => {
console.log(res.data);
},
fail: (err) => {
console.error(err);
}
});

5.2 封装请求工具

5.2.1 创建 request.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// utils/request.js

const baseURL = 'https://api.example.com';

// 请求拦截器
const requestInterceptor = (config) => {
// 添加 token
const token = uni.getStorageSync('token');
if (token) {
config.header.Authorization = `Bearer ${token}`;
}
return config;
};

// 响应拦截器
const responseInterceptor = (response) => {
if (response.statusCode === 200) {
return response.data;
} else {
uni.showToast({
title: '请求失败',
icon: 'none'
});
return Promise.reject(response);
}
};

// 封装请求方法
const request = (options) => {
options.url = baseURL + options.url;
options = requestInterceptor(options);

return new Promise((resolve, reject) => {
uni.request({
...options,
success: (res) => {
const result = responseInterceptor(res);
resolve(result);
},
fail: (err) => {
reject(err);
}
});
});
};

// 封装 GET 请求
export const get = (url, params) => {
return request({
url,
method: 'GET',
data: params
});
};

// 封装 POST 请求
export const post = (url, data) => {
return request({
url,
method: 'POST',
data
});
};

export default request;

5.2.2 使用封装的请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { get, post } from '@/utils/request';

// GET 请求
get('/user/list', { page: 1, limit: 10 })
.then((res) => {
console.log(res);
})
.catch((err) => {
console.error(err);
});

// POST 请求
post('/user/login', { username: 'admin', password: '123456' })
.then((res) => {
console.log(res);
})
.catch((err) => {
console.error(err);
});

5.3 跨域问题

5.3.1 开发环境跨域

在 HBuilderX 中,可以在 manifest.json 中配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"h5": {
"devServer": {
"proxy": {
"/api": {
"target": "https://api.example.com",
"changeOrigin": true,
"pathRewrite": {
"^/api": ""
}
}
}
}
}
}

5.3.2 生产环境跨域

生产环境需要在服务器端配置 CORS:

1
2
3
4
5
6
7
8
9
location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
add_header Access-Control-Allow-Headers 'Content-Type, Authorization';

if ($request_method = 'OPTIONS') {
return 204;
}
}

6. 跨平台适配

6.1 平台差异

uni-app 虽然支持多端运行,但不同平台之间仍然存在一些差异。

6.1.1 平台差异表

功能H5微信小程序支付宝小程序百度小程序头条小程序QQ小程序
支付支持支持支持支持支持支持
分享支持支持支持支持支持支持
地图支持支持支持支持支持支持
扫码支持支持支持支持支持支持
推送不支持支持支持支持支持支持

6.2 条件编译

使用条件编译可以针对不同平台编写不同的代码。

6.2.1 条件编译语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<template>
<view>
<!-- #ifdef H5 -->
<view>这是 H5 平台的内容</view>
<!-- #endif -->

<!-- #ifdef MP-WEIXIN -->
<view>这是微信小程序平台的内容</view>
<!-- #endif -->

<!-- #ifdef APP-PLUS -->
<view>这是 App 平台的内容</view>
<!-- #endif -->
</view>
</template>

<script>
export default {
mounted() {
// #ifdef H5
console.log('H5 平台');
// #endif

// #ifdef MP-WEIXIN
console.log('微信小程序平台');
// #endif
}
};
</script>

<style>
/* #ifdef H5 */
view {
font-size: 16px;
}
/* #endif */

/* #ifdef MP-WEIXIN */
view {
font-size: 32rpx;
}
/* #endif */
</style>

6.2.2 平台标识

平台标识
H5H5
微信小程序MP-WEIXIN
支付宝小程序MP-ALIPAY
百度小程序MP-BAIDU
头条小程序MP-TOUTIAO
QQ小程序MP-QQ
钉钉小程序MP-DINGTALK
淘宝小程序MP-TAOBAO
AppAPP-PLUS
App-nvueAPP-NVUE
快应用QUICKAPP-WEBVIEW

6.3 适配方案

6.3.1 尺寸适配

  • 使用 rpx 单位:rpx 是相对单位,1rpx = 屏幕宽度/750
  • 避免使用 px 单位:px 是绝对单位,在不同屏幕尺寸下显示效果不同
  • 使用 flex 布局:flex 布局可以自适应不同屏幕尺寸

6.3.2 样式适配

  • 使用 uni.scss 中的全局变量
  • 使用条件编译针对不同平台编写不同的样式
  • 使用 CSS 变量实现主题切换

6.3.3 API 适配

  • 使用 uni-app 封装的统一 API
  • 对于平台特有的 API,使用条件编译
  • 封装平台差异,提供统一的调用接口

7. 性能优化

7.1 页面性能优化

7.1.1 渲染性能

  • 减少节点数量:避免嵌套层级过深
  • 使用虚拟列表:对于长列表,使用虚拟列表减少 DOM 节点
  • 避免频繁更新:使用防抖、节流减少频繁更新
  • 使用分包加载:减小主包体积,提高加载速度

7.1.2 启动性能

  • 减少主包体积:将不常用的页面放入分包
  • 预加载:使用 uni.preloadPage() 预加载页面
  • 骨架屏:使用骨架屏提升用户体验
  • 懒加载:图片、组件懒加载

7.2 网络性能优化

7.2.1 请求优化

  • 合并请求:减少 HTTP 请求次数
  • 缓存策略:使用本地缓存减少重复请求
  • 压缩数据:使用 gzip 压缩数据
  • CDN 加速:使用 CDN 加速静态资源

7.2.2 图片优化

  • 图片压缩:使用压缩后的图片
  • 图片格式:使用 WebP 格式图片
  • 图片懒加载:使用 uni.createIntersectionObserver() 实现图片懒加载
  • 占位符:使用占位符提升用户体验

7.3 代码优化

7.3.1 代码分割

  • 分包加载:将应用分为主包和分包
  • 按需加载:使用动态导入按需加载组件

7.3.2 内存优化

  • 及时销毁:组件销毁时清理定时器、事件监听器
  • 减少全局变量:避免使用过多的全局变量
  • 合理使用闭包:避免内存泄漏

8. 企业级应用开发

8.1 项目架构

8.1.1 目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
├── api/             # API 接口
├── components/ # 组件
├── pages/ # 页面
├── static/ # 静态资源
├── store/ # 状态管理
├── utils/ # 工具函数
├── services/ # 服务层
├── middlewares/ # 中间件
├── filters/ # 过滤器
├── mixins/ # 混入
├── App.vue # 应用入口
├── main.js # 应用入口
├── manifest.json # 应用配置
├── pages.json # 页面配置
└── uni.scss # 全局样式

8.1.2 分层架构

  • API 层:封装接口调用
  • Service 层:封装业务逻辑
  • Store 层:状态管理
  • Component 层:UI 组件
  • Page 层:页面

8.2 开发规范

8.2.1 命名规范

  • 文件命名:使用小写字母,单词之间用连字符连接
  • 组件命名:使用 PascalCase 命名法
  • 变量命名:使用 camelCase 命名法
  • 常量命名:使用 UPPER_SNAKE_CASE 命名法
  • 函数命名:使用 camelCase 命名法

8.2.2 代码规范

  • 缩进:使用 2 个空格
  • 分号:使用分号结束语句
  • 引号:使用单引号
  • 括号:使用大括号包裹代码块
  • 注释:使用 JSDoc 注释

8.3 版本控制

8.3.1 Git 规范

  • 分支管理

    • master:主分支
    • develop:开发分支
    • feature:功能分支
    • hotfix:修复分支
  • 提交规范

    • feat:新增功能
    • fix:修复 bug
    • docs:文档更新
    • style:代码风格调整
    • refactor:代码重构
    • test:测试代码
    • chore:构建工具或依赖更新

8.4 部署与发布

8.4.1 构建流程

  1. 代码检查:使用 ESLint 检查代码
  2. 单元测试:运行单元测试
  3. 构建:使用 HBuilderX 或命令行构建
  4. 部署:部署到服务器或发布到应用商店

8.4.2 发布平台

  • H5:部署到 Web 服务器
  • 微信小程序:发布到微信小程序平台
  • 支付宝小程序:发布到支付宝小程序平台
  • 百度小程序:发布到百度小程序平台
  • 头条小程序:发布到头条小程序平台
  • QQ小程序:发布到 QQ 小程序平台
  • App:发布到应用商店

8.5 监控与错误处理

8.5.1 错误监控

  • try/catch:捕获同步错误
  • Promise.catch:捕获异步错误
  • 全局错误处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// main.js
Vue.config.errorHandler = (err, vm, info) => {
console.error('Vue 错误:', err);
console.error('错误信息:', info);
// 上报错误
};

// 监听 unhandledrejection 事件
window.addEventListener('unhandledrejection', (event) => {
console.error('未处理的 Promise 错误:', event.reason);
// 上报错误
});

// 监听 error 事件
window.addEventListener('error', (event) => {
console.error('全局错误:', event.error);
// 上报错误
});

8.5.2 性能监控

  • 首屏加载时间
1
2
3
4
5
6
7
8
9
// 记录开始时间
const startTime = Date.now();

// 监听页面加载完成
window.addEventListener('load', () => {
const loadTime = Date.now() - startTime;
console.log('首屏加载时间:', loadTime);
// 上报性能数据
});
  • 页面切换时间
1
2
3
4
5
6
7
8
9
10
11
// 监听页面显示
uni.onPageShow((res) => {
const pageStartTime = Date.now();

// 监听页面初次渲染完成
uni.onPageReady((res) => {
const renderTime = Date.now() - pageStartTime;
console.log('页面渲染时间:', renderTime);
// 上报性能数据
});
});

9. 实战案例

9.1 电商应用

9.1.1 功能模块

  • 首页:轮播图、分类导航、推荐商品
  • 商品列表:商品展示、筛选、排序
  • 商品详情:商品信息、规格选择、加入购物车
  • 购物车:商品管理、数量修改、结算
  • 订单:订单列表、订单详情、订单状态
  • 个人中心:用户信息、收货地址、订单管理

9.1.2 技术实现

  • 状态管理:使用 Vuex 管理全局状态
  • 网络请求:封装 request 工具
  • UI 组件:使用 uni-ui 组件库
  • 支付:集成各平台支付
  • 分享:集成各平台分享

9.2 企业管理系统

9.2.1 功能模块

  • 登录:账号密码登录、验证码登录
  • 首页:数据看板、快捷入口
  • 用户管理:用户列表、用户详情、添加/编辑用户
  • 角色管理:角色列表、权限配置
  • 权限管理:菜单权限、按钮权限
  • 数据统计:数据图表、报表导出

9.2.2 技术实现

  • 权限控制:基于角色的权限控制
  • 数据可视化:使用 echarts 实现数据图表
  • 表单验证:使用 async-validator 进行表单验证
  • 导出功能:使用 xlsx 库实现 Excel 导出
  • WebSocket:实时数据推送

10. 总结与展望

10.1 uni-app 的优势

  • 开发效率高:一套代码多端运行
  • 性能优异:底层使用原生渲染
  • 生态丰富:大量的 UI 组件和插件
  • 学习成本低:使用 Vue.js 语法
  • 跨平台能力强:支持 10+ 个平台

10.2 uni-app 的局限性

  • 平台差异:不同平台之间存在差异
  • 原生能力:部分原生能力需要使用插件
  • 性能优化:需要针对不同平台进行优化

10.3 未来发展

  • Vue 3 支持:全面支持 Vue 3
  • 更多平台:支持更多的平台
  • 更好的性能:进一步提升性能
  • 更丰富的生态:完善生态系统

10.4 学习建议

  • 掌握基础知识:Vue.js、JavaScript、CSS
  • 实践项目:通过实际项目巩固知识
  • 关注官方文档:及时了解最新特性
  • 社区交流:参与社区讨论,分享经验
  • 持续学习:关注前端技术发展趋势

附录

常用 API 参考

API说明平台支持
uni.request网络请求所有平台
uni.setStorageSync存储数据所有平台
uni.getStorageSync获取存储数据所有平台
uni.navigateTo页面跳转所有平台
uni.showToast显示提示信息所有平台
uni.showLoading显示加载动画所有平台
uni.hideLoading隐藏加载动画所有平台
uni.showModal显示模态框所有平台
uni.chooseImage选择图片所有平台
uni.uploadFile上传文件所有平台
uni.downloadFile下载文件所有平台
uni.getSystemInfoSync获取系统信息所有平台
uni.getLocation获取位置信息所有平台
uni.makePhoneCall拨打电话所有平台

常见问题与解决方案

Q: 跨域问题如何解决?
A: 在开发环境中,在 manifest.json 中配置 devServer.proxy;在生产环境中,在服务器端配置 CORS。

Q: 如何优化首屏加载速度?
A: 减少主包体积、使用分包加载、预加载页面、使用骨架屏、图片懒加载。

Q: 如何处理平台差异?
A: 使用条件编译、封装平台差异、参考官方文档的平台差异说明。

Q: 如何实现图片懒加载?
A: 使用 uni.createIntersectionObserver() 实现图片懒加载。

Q: 如何实现自定义导航栏?
A: 在 pages.json 中设置 navigationStyle: ‘custom’,然后自定义导航栏组件。

Q: 如何实现下拉刷新和上拉加载?
A: 在 pages.json 中配置 enablePullDownRefresh: true,然后在页面中实现 onPullDownRefresh 和 onReachBottom 方法。

Q: 如何实现全局状态管理?
A: 使用 Vuex 或 Pinia 实现全局状态管理。

Q: 如何实现路由拦截?
A: 使用 uni.addInterceptor() 实现路由拦截。

Q: 如何实现支付功能?
A: 使用 uni.requestPayment() 实现支付功能,注意不同平台的参数差异。

Q: 如何实现分享功能?
A: 在页面中实现 onShareAppMessage 方法,注意不同平台的参数差异。

资源推荐

开发工具

结语

uni-app 作为一个跨平台开发框架,为开发者提供了一种高效、便捷的开发方式。通过学习本读书笔记,你应该已经掌握了 uni-app 的核心概念、开发技巧和最佳实践。

在实际开发中,你需要根据具体项目的需求,灵活运用这些知识,同时关注官方文档的更新,及时了解新特性和最佳实践。

最后,希望你在 uni-app 开发的道路上越走越远,开发出更多优秀的跨平台应用!