主题
uni-app 入门
文档:https://uniapp.dcloud.io/quickstart?id=发布uni-app
一、快速上手
下载开发工具 HBuilderX:https://www.dcloud.io/hbuilderx.html
1. 创建 uni-app
点击工具栏里的文件 -> 新建 -> 项目
- 输入工程名;2. 选择项目目录文件;3. 选择 uni-ui 模板;4. 选择 vue 的版本,点击创建

提示:在代码区输入字母 u,即可通过代码助手列出所有可用组件。光标置于组件名称处按 F1,即可查看组件文档
2. 运行 uni-app
(1)浏览器运行
点击工具栏的运行 -> 运行到浏览器 -> 选择浏览器
(2)真机运行
步骤一:开启 USB 调试
Android 版:在设置,系统,关于手机中找到版本号,连续点击五次,会进入开发者模式,然后回退一下,有个开发者选项,然后开启 USB 调试,(华为手机要关闭掉监控 ADB 安装应用选项:)
步骤二:进行授权
使用 USB 将手机插入电脑。如果设备出现调试授权提示,请授权你的电脑可以访问该设备。

步骤三:运行程序
点击工具栏的运行 -> 真机运行 -> 选择运行的设备
(3)微信开发者工具里运行
下载微信开发者工具:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html
在微信开发者工具中,选择设置 -> 安全设置 -> 开启服务端口
提示:如果是第一次使用,还需配置微信开发者工具的安装目录。在运行到小程序模拟器 > 运行设置中配置

点击工具栏的运行 -> 运行到小程序模拟器 -> 微信开发者工具

3. 安装常用插件
插件市场:https://ext.dcloud.net.cn/?cat1=1&cat2=11
Prettier:在格式化时可选择 Prettier
eslint-plugin-vue
二、VSCode 改造
如果使用 VSCode 开发习惯了,使用 HBuilderX 开发可能不太顺手。可使用 HBuilderX 运行程序,使用 VSCode 修改程序代码。使用 VSCode 开发 uni-app,需做一些额外配置。
1. TypeScript
使 TypeScript 能够识别 uni 相关 API;并且配置路径映射,配合别名使用
(1)安装
bash
yarn add @types/node -D
yarn add @dcloudio/types -D
yarn add @dcloudio/uni-app -D
yarn add vue@3.2.6 @vue/runtime-dom@3.2.6 -Dvue 的版本是依据 D:\HBuilderX\plugins\hbuilderx-language-services\builtin-dts\node_modules\vue@3 目录下的 Vue 版本
(2)新建 tsconfig.json
json
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"moduleResolution": "node",
"esModuleInterop": true,
"sourceMap": true,
"skipLibCheck": true,
"importHelpers": true,
"allowSyntheticDefaultImports": true,
"useDefineForClassFields": true,
"resolveJsonModule": true,
"lib": ["esnext", "dom"],
"types": ["@dcloudio/types", "node"],
"baseUrl": ".",
"paths": { "@/*": ["./*"] }
},
"exclude": ["node_modules", "uni_modules", "unpackage", "src/**/*.nvue"]
}2. ESlint、Prettier
(1)安装
bash
//eslint 安装
yarn add eslint@^8.39.0 -D
//eslint vue插件安装
yarn add eslint-plugin-vue@^9.11.0 -D
//eslint 识别ts语法
yarn add @typescript-eslint/parser@^6.19.0 -D
//eslint ts默认规则补充
yarn add @typescript-eslint/eslint-plugin@^6.19.0 -D
//eslint prettier插件安装
yarn add eslint-plugin-prettier@^5.1.3 -D
//用来解决与eslint的冲突
yarn add eslint-config-prettier@^9.1.0 -D
//安装prettier
yarn add prettier@^3.2.4 -D(2)新建 .eslintrc.cjs
js
module.exports = {
globals: {
uni: "readonly", // 声明 uni 为全局只读变量
},
parser: "vue-eslint-parser",
extends: [
"eslint:recommended", //继承 ESLint 内置的推荐规则
"plugin:vue/vue3-recommended", // 继承 Vue.js 3 的推荐规则
"plugin:@typescript-eslint/recommended", //继承 TypeScript ESLint 插件的推荐规则
"plugin:prettier/recommended", //继承 Prettier 的推荐规则
"eslint-config-prettier", //关闭 ESLint 中与 Prettier 冲突的规则
],
parserOptions: {
ecmaVersion: "latest",
parser: "@typescript-eslint/parser",
sourceType: "module",
ecmaFeatures: {
jsx: true,
},
},
ignorePatterns: [
"dist",
"node_modules",
".eslintrc.cjs",
"commitlint.config.cjs",
],
plugins: ["vue", "@typescript-eslint", "prettier"],
rules: {
"vue/multi-word-component-names": "off", // 禁用vue文件强制多个单词命名
"vue/require-default-prop": "off", //允许props没有默认值
"@typescript-eslint/no-explicit-any": "off", //允许使用any
"@typescript-eslint/no-this-alias": [
"error",
{
allowedNames: ["that"], // this可用的局部变量名称
},
],
"@typescript-eslint/ban-ts-comment": "off", //允许使用@ts-ignore
"@typescript-eslint/no-non-null-assertion": "off", //允许使用非空断言
"no-console": [
//提交时不允许有console.log
"warn",
{
allow: ["warn", "error"],
},
],
"no-debugger": "warn", //提交时不允许有debugger
},
};(3)新建 .prettierrc
json
{
"endOfLine": "auto",
"printWidth": 120,
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "all",
"bracketSpacing": true
}(4)新建 .prettierignore
text
# 忽略格式化文件 (根据项目需要自行添加)
node_modules
dist(5)重启 vscode 使配置生效
(6)配置 package.json
json
"scripts": {
"lint": "eslint --fix --ext .js,.ts,.vue --report-unused-disable-directives --max-warnings 0"
},运行 yarn run lint 修复一些 ESlint 能够自动修复的问题,例如双引号改为单引号
3. vue 语法提示
在 VScode 中,要使用 Vue 语法提示,除了安装 Vue - Official 插件,还需配置 vite.config.js
(1)安装
bash
yarn add @vitejs/plugin-vue -D提示:不要配置 vite.config.js,否则 HBuilderX 默认配置会失效,导致启动报错
三、差异点
1. 标签
组件标签靠近小程序规范(div 使用 <view>,span 使用 <text>)
2. 接口
接口能力靠近微信小程序规范,但需将前缀 wx 替换为 uni
3. 尺寸单位
px、%、rpx
rpx 与微信小程序 rpx 效果相同。
举例说明:
若设计稿宽度为 640px,元素 A 在设计稿上的宽度为 100px,那么元素 A 在 uni-app 里面的宽度应该设为:750 * 100 / 640,结果为:117rpx。
若设计稿宽度为 375px,元素 B 在设计稿上的宽度为 375px,那么元素 B 在 uni-app 里面的宽度应该设为:750 * 375 / 375,结果为:750rpx。
若设计稿宽度为 750px,元素 B 在设计稿上的宽度为 750px,那么元素 B 在 uni-app 里面的宽度应该设为:750 * 750 / 750,结果为:750rpx。
4. 引用组件
传统 vue 项目开发,引用组件需要导入 - 注册 - 使用三个步骤,如下:
vue
<template>
<view>
<!-- 3.使用组件 -->
<uni-rate text="1"></uni-rate>
</view>
</template>
<script>
// 1. 导入组件
import uniRate from "@/components/uni-rate/uni-rate.vue";
export default {
components: { uniRate }, // 2. 注册组件
};
</script>Vue 3.x 增加了 script setup 特性,将三步优化为两步,无需注册步骤,更为简洁
uni-app 的 easycom 机制,将组件引用进一步优化,开发者只管使用,无需考虑导入和注册(将组件定义在最外层的 components 下,能够直接在页面使用)
vue
<template>
<view>
<!-- 1.使用组件 -->
<uni-rate text="1"></uni-rate>
</view>
</template>
<script></script>提示:对于静态文件使用绝对路径(从根目录开始),但 js 文件不支持绝对路径的方式引入,可使用相对路径,或路径别名 @(指向项目根目录)
5. 条件编译
条件编译是用特殊的注释作为标记,在编译时根据这些特殊的注释,将注释里面的代码编译到不同平台。
写法:以 #ifdef 或 #ifndef 加 %PLATFORM%,以 #endif 结尾
#ifdef:if defined 仅在某平台存在#ifndef:if not defined 除了某平台均存在%PLATFORM%:平台名称



在 HBuilderX 中,按 ctrl+alt+/ 即可生成正确注释。支持 API 条件编译,组件条件编译,样式条件编译,pages.json 条件编译

static 目录的条件编译。static 目录下新建不同平台的专有目录(目录名称同 %PLATFORM%,但字母均为小写),专有目录下的静态资源只有在特定平台才会被编译进去。
如以下目录结构,a.png 只有在微信小程序平台才会编译进去,b.png 在所有平台都会被编译。
text
┌─static
│ ├─mp-weixin
│ │ └─a.png
│ └─b.png
├─main.js
├─App.vue
├─manifest.json
└─pages.json整体目录条件编译。在 uni-app 项目根目录创建 platforms 目录,然后在下面进一步创建 app-plus、mp-weixin 等子目录,存放不同平台的文件
注意:platforms 目录下只支持放置页面文件(即页面 vue 文件),如果需要对其他资源条件编译建议使用 static 目录的条件编译
6. Tab 高度
在布局的时候,有时候需要考虑底部 Tab 栏高度的占位
CSS:
css
var(--tab-bar-height)JS:
js
uni.getSystemInfo({
success: (res) => {
const { screenHeight, windowHeight } = res;
this.tabBarHeight = screenHeight - windowHeight; // 底部 TabBar 高度
},
});提示:对于整个页面的高度,在 H5 中时包含底部 Tab 高度的,因此会遮挡,需额外设置 padding-bottom。在微信小程序中,整个页面的高度是不包含底部 Tab 高度
四、全局配置
1. 引入字体图标
首先将图标加到购物车,然后选择 Font class 点击下载到本地,然后将 iconfont 开头的所有文件都复制到项目的 static 文件夹下新建的 icon 目录。在 App.vue 的 style 区域全局引入,或者在页面的 style 区域单独引入。
css
@import url("./static/icon/iconfont.css");修改 iconfont.css 文件,增加路径 ~@/static/icon/...
![]()
之后就可以在页面中使用,<view class="iconfont icon-zhuti_tiaosepan_o"></view>
2. H5 跨域
方案一:使用 HBuilderX 内置浏览器
方案二:使用 Chrome 代理插件
地址:https://chromewebstore.google.com/detail/allow-cors-access-control/lhobafahddgcelffkeicbaginigeejlf
安装完扩展后,选择开启

3. 小程序配置域名白名单
在各个小程序平台运行时,网络相关的 API 在使用前需要配置域名白名单
以微信小程序为例,登录小程序后台 https://mp.weixin.qq.com/wxamp/devprofile/get_profile
在开发 -> 开发管理 -> 开发设置 -> 服务器域名中进行配置(request,socket,uploadFile 都需配置)

注意点:
- 域名不能使用 IP 地址或 localhost,且不能带端口号
- 域名必须经过 ICP 备案
- 对于每个接口,分别可以配置最多 20 个域名
在本地开发中,选择小程序开发者工具 -> 详情 -> 本地设置 -> 打开不校验合法域名。等到上线时再打开去检查域名的合法性
4. 拦截器
使用 uni.addInterceptor 可实现全局拦截功能
(1)请求拦截器
新建 interceptors/request.ts
ts
const baseUrl = "";
// 拦截器配置
const httpInterceptor = {
// 拦截前触发
invoke(options: CustomRequestOptions) {
// 添加
options.url = baseUrl + options.url;
// 添加 token 请求头标识
options.header.Authorization = `Bearer ${token}`;
},
};
export const requestInterceptor = {
install() {
// 拦截 request 请求
uni.addInterceptor("request", httpInterceptor);
// 拦截 uploadFile 文件上传
uni.addInterceptor("uploadFile", httpInterceptor);
},
};新建 interceptors/index.ts
ts
export { requestInterceptor } from "./request";修改 main.ts
ts
import { createSSRApp } from "vue";
import App from "./App.vue";
import { requestInterceptor } from "./interceptors";
export function createApp() {
const app = createSSRApp(App);
app.use(requestInterceptor);
return {
app,
};
}(2)路由拦截器
新建 interceptors/route.ts
ts
const loginRoute = "/pages/login/index";
const navigateToInterceptor = {
invoke({ url }: { url: string }) {
//可根据登录状态做一些拦截操作
return true;
},
};
export const routeInterceptor = {
install() {
uni.addInterceptor("navigateTo", navigateToInterceptor);
uni.addInterceptor("reLaunch", navigateToInterceptor);
uni.addInterceptor("redirectTo", navigateToInterceptor);
uni.addInterceptor("switchTab", navigateToInterceptor);
},
};导入方式类似于请求拦截器
5. 网络请求
对 uni.request 进行封装,减少重复代码
(1)新建 utils/request.ts
ts
// 定义请求配置类型
interface RequestConfig {
url: string;
method?:
| "GET"
| "POST"
| "PUT"
| "DELETE"
| "OPTIONS"
| "HEAD"
| "CONNECT"
| "TRACE";
data?: any;
params?: any; // URL 参数 (uni.request 本身不支持 params,需手动处理)
header?: Record<string, string>;
showLoading?: boolean;
responseType?: "arraybuffer" | "text" | "json";
[key: string]: any; // 允许其他自定义属性
}
// 定义响应数据结构(根据后端接口约定调整)
interface ResponseData<T = any> {
code: number;
msg: string;
data: T;
}
// 创建请求实例
class Request {
// 核心请求方法
request<T = any>(config: RequestConfig): Promise<T> {
// 合并配置
let mergedConfig: RequestConfig = {
method: "GET",
showLoading: false,
...config,
header: { ...config.header },
};
// 处理 URL 参数(手动拼接)
if (mergedConfig.params) {
const params = new URLSearchParams(mergedConfig.params).toString();
mergedConfig.url += `?${params}`;
delete mergedConfig.params;
}
// 显示 Loading
if (mergedConfig.showLoading) {
uni.showLoading({ title: "加载中...", mask: true });
}
// 发送请求
return new Promise((resolve, reject) => {
uni.request({
url: mergedConfig.url,
method: mergedConfig.method,
data: mergedConfig.data,
header: mergedConfig.header,
responseType: mergedConfig.responseType,
success: async (res) => {
try {
const data = res.data as ResponseData<T>;
resolve(data.data);
} catch (err) {
reject(err);
}
},
fail: (err) => {
reject(new Error(`网络错误: ${err.errMsg}`));
},
complete: () => {
// 关闭 Loading
if (mergedConfig.showLoading) {
uni.hideLoading();
}
},
});
});
}
get<T>(
url: string,
params?: Record<string, any>,
showLoading?: boolean,
): Promise<T> {
return this.request({ method: "GET", url, params, showLoading });
}
delete<T>(
url: string,
data?: Record<string, any>,
showLoading?: boolean,
): Promise<T> {
return this.request({ method: "DELETE", url, data, showLoading });
}
post<T>(
url: string,
data?: Record<string, any>,
showLoading?: boolean,
): Promise<T> {
return this.request({ method: "POST", url, data, showLoading });
}
put<T>(
url: string,
data?: Record<string, any>,
showLoading?: boolean,
): Promise<T> {
return this.request({ method: "PUT", url, data, showLoading });
}
}
// 创建实例并配置拦截器
const http = new Request();
export default http;(2)定义 API 接口类型
ts
// api/types.ts
// 登录接口响应数据
export interface LoginResponse {
userId: string;
username: string;
token: string;
}
// 用户信息接口响应数据
export interface UserInfoResponse {
nickname: string;
avatar: string;
email: string;
}(3)统一管理 API
ts
// api/index.ts
import request from "@/utils/request";
import type { LoginResponse, UserInfoResponse } from "./types";
// 登录接口
export const login = (data: { username: string; password: string }) => {
return request.post<LoginResponse>("/user/login", data, true);
};6. 微信小程序开启组件按需注入
json
{
"lazyCodeLoading": "requiredComponents"
}五、pages.json
1. pages
每次新建页面,均需在 pages.json 中配置 pages 列表;未在 pages.json -> pages 中注册的页面,uni-app 会在编译阶段进行忽略。
在 pages 文件夹上右击,新建页面,HBuilderX 会自动在 pages.json 中完成页面注册。
配置项中的第一个页面,作为当前工程的首页(启动页)
提示:
删除或修改页面时,记得在 pages.json 中同步修改
新建页面后,需在编译器中点击重新运行编译
如果想取消原生导航栏
json
"pages": [{
"path": "pages/index/index",
"style": {
"navigationStyle": "custom" //取消原生导航
}
},
],2. tabBar
json
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#3cc51f",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"height": "50px",
"fontSize": "10px",
"iconWidth": "24px",
"spacing": "3px",
"list": [
{
"text": "菜谱",
"pagePath": "pages/index/index",
"iconPath": "static/tabs/menus.png",
"selectedIconPath": "static/tabs/menus-active.png"
},
{
"text": "电影",
"pagePath": "pages/message/index",
"iconPath": "static/tabs/movie.png",
"selectedIconPath": "static/tabs/movie-active.png"
}
]
}提示:
(1)tabBar 中的 list 是一个数组,只能配置最少 2 个、最多 5 个 tab,tab 按数组的顺序排序。
(2)tabbar 切换第一次加载时可能渲染不及时,可以在每个 tabbar 页面的 onLoad 生命周期里先弹出一个等待雪花(hello uni-app 使用了此方式)
(3)tabbar 的页面展现过一次后就保留在内存中,再次切换 tabbar 页面,只会触发每个页面的 onShow,不会再触发 onLoad。
(4)顶部的 tabbar 目前仅微信小程序上支持。需要用到顶部选项卡的话,建议不使用 tabbar 的顶部设置,而是自己做顶部选项卡,可参考 hello uni-app->模板->顶部选项卡。
3. globalStyle
用于设置应用的状态栏、导航条、标题、窗口背景色等。
json
"globalStyle": {
"navigationBarTextStyle": "white",
"navigationBarTitleText": "网易云音乐",
"navigationBarBackgroundColor": "#d43c33",
"backgroundColor": "#FFFFFF",
"maxWidth": 375
},更多配置:https://uniapp.dcloud.net.cn/collocation/pages.html#globalstyle
六、使用
1. 生命周期
(1)应用的生命周期(在 App.vue 页面定义)
- onLaunch:当 uni-app 初始化完成时触发(全局只触发一次)
- onShow:当 uni-app 启动,或从后台进入前台显示
- onHide:当 uni-app 从前台进入后台
- onError:当 uni-app 报错时触发
其他的看文档:https://uniapp.dcloud.io/collocation/frame/lifecycle?id=应用生命周期
(2)页面的生命周期
- onLoad:监听页面加载,其参数为上个页面传递的数据(用于页面传参),在该生命周期中获取接口数据
- onReady:监听页面渲染完成(只会触发一次)
- onShow:监听页面显示,页面每次出现在屏幕上触发
- onHide:监听页面隐藏
- onUnload:监听页面卸载
- onPullDownRefresh:监听下拉事件
- onReachBottom:监听触底事件
其他的看文档:https://uniapp.dcloud.io/collocation/frame/lifecycle?id=页面生命周期
2. 下拉刷新
一般不配置全局下拉刷新,哪个页面需要就配置哪个页面的刷新
(1)需要在 pages.json 里,找到当前页面的 pages 节点,并在 style 选项中开启 enablePullDownRefresh。
json
{
"path": "pages/message/index",
"style": {
"enablePullDownRefresh": true
}
}(2)在 js 中定义 onPullDownRefresh 处理函数(和 onload 生命周期函数同级),监听用户页面下拉刷新事件。
当处理完数据后,调用 uni.stopPullDownRefresh() 停止刷新动作
js
onPullDownRefresh() {
console.log('触发了下拉刷新');
setTimeout(() => {
uni.stopPullDownRefresh()
}, 2000)
},(3)可以通过触发点击事件,调用 uni.startPullDownRefresh(OBJECT) 来模拟用户的下拉刷新
3. 上拉加载
(1)配置页面上拉触底事件触发时距页面底部距离
json
"globalStyle": {
"onReachBottomDistance": 50
},(2)在 js 中定义 onReachBottom 处理函数(和 onload 生命周期函数同级),监听用户页面上拉加载事件。
js
onReachBottom() {
console.log('上拉')
},4. 数据缓存
(1)异步存储
js
uni.setStorage({
key: "id",
data: 80,
success() {
console.log("存储成功");
},
});(2)异步获取
js
uni.getStorage({
key: "id",
success(res) {
console.log("获取成功", res.data);
},
});(3)同步存储
js
try {
uni.setStorageSync("storage_key", "hello");
} catch (e) {
// error
}(4)同步获取
js
try {
const value = uni.getStorageSync("storage_key");
if (value) {
console.log(value);
}
} catch (e) {
// error
}(5)异步删除
js
uni.removeStorage({
key: "storage_key",
success: function (res) {
console.log("success");
},
});(6)同步删除
js
try {
uni.removeStorageSync("storage_key");
} catch (e) {
// error
}(7)异步清空
js
uni.clearStorage();(8)同步清空
js
try {
uni.clearStorageSync();
} catch (e) {
// error
}注意:
- H5 端为 localStorage,浏览器限制 5M 大小,是缓存概念,可能会被清理
- App 端为原生的 plus.storage,无大小限制,不是缓存,是持久化
- 各个小程序端为其自带的 storage api,数据存储生命周期跟小程序本身一致,即除用户主动删除或超过一定时间被自动清理,否则数据都一直可用。
- 微信小程序单个 key 允许存储的最大数据长度为 1MB,所有数据存储上限为 10MB。
- 支付宝小程序单条数据转换成字符串后,字符串长度最大 200 * 1024。同一个支付宝用户,同一个小程序缓存总上限为 10MB。
- 百度、字节跳动小程序文档未说明大小限制
5. 路由跳转
(1)保留当前页面,跳转到应用内的某个页面
js
uni.navigateTo({ url: `../login/login?id=${value}` });参数通过 ? 拼接在 url 上,新页面在 onLoad 生命周期获取。
js
onLoad(options) {
console.log(options) //{id: "80"}
}提示:不要将过多的信息存储在 url 上,可传递 Id 等关键信息,然后使用 pinia 存储全部数据,使用 Id 去找相关信息
(2)关闭当前页面,跳转到应用内的某个页面
js
uni.redirectTo();(3)关闭所有页面,打开到应用内的某个页面
js
uni.reLaunch();(4)跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
路径不能带参数,可以将值进行数据缓存
js
uni.switchTab();提示:tabBar 页面通过 uni.navigateTo 跳转到其他页面,是会保留当前页面,所以当使用 uni.switchTab 跳转回来时,是不会触发 onLoad 钩子函数。只会触发 onShow 钩子函数
(5)关闭当前页面,返回上一页面或多级页面
js
uni.navigateBack({ delta: 1 });6. 发布/订阅
- 发布:
uni.$emit - 订阅:
uni.$on - 取消订阅:
uni.$off - 只订阅一次:
uni.$once
7. Pinia
uni-app 内置了 Pinia,不需要额外安装,如果使用 VScode 开发,还需手动安装 pinia(与 vue 一样,注意版本,目前 2.1.7)
(1)在项目根目录新建 store 文件夹
用来存放状态管理相关数据
(2)在 main.js 中编写以下代码:
js
import App from "./App";
import { createSSRApp } from "vue";
import * as Pinia from "pinia";
export function createApp() {
const app = createSSRApp(App);
app.use(Pinia.createPinia());
return {
app,
Pinia, // 此处必须将 Pinia 返回
};
}(3)首先创建一个 Store:
js
// stores/counter.js
import { defineStore } from "pinia";
export const useCounterStore = defineStore("counter", {
state: () => {
return { count: 0 };
},
// 也可以这样定义
// state: () => ({ count: 0 })
actions: {
increment() {
this.count++;
},
},
});(4)使用
vue
<template>
<view>
<text>{{ count }}</text>
<button @click="increment">按钮</button>
</view>
</template>
<script setup>
import { storeToRefs } from "pinia";
import { useCounterStore } from "@/stores/counter";
const counterStore = useCounterStore();
const { count } = storeToRefs(counterStore);
const { increment } = counterStore;
</script>七、打包发布
1. 分包
在 pages.json 文件中配置
| 属性 | 类型 | 必填 | 描述 | 平台兼容 |
|---|---|---|---|---|
| subPackages | Object Array | 否 | 分包加载配置 | H5 不支持 |
| preloadRule | Object | 否 | 分包预下载规则 | 微信小程序 |
subPackages:
| 属性 | 类型 | 是否必填 | 描述 |
|---|---|---|---|
| root | String | 是 | 子包的根目录 |
| pages | Array | 是 | 子包由哪些页面组成,参数同 pages |
preloadRule:
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| packages | String Array | 是 | 无 | 进入页面后预下载分包的 root 或 name。__APP__ 表示主包。 |
| network | String | 否 | wifi | 在指定网络下预下载,可选值为:all(不限网络)、wifi(仅 wifi 下预下载) |
App 下开启分包,除在 pages.json 中配置分包规则外,还需要在 manifest 中设置在 app 端开启分包设置,详见:https://uniapp.dcloud.io/collocation/manifest?id=app-vue-optimization
注意:
- subPackages 里的 pages 的路径是 root 下的相对路径,不是全路径。
- 微信小程序每个分包的大小是 2M,总体积一共不能超过 20M。
- 百度小程序每个分包的大小是 2M,总体积一共不能超过 8M。
- 支付宝小程序每个分包的大小是 2M,总体积一共不能超过 8M。
- QQ 小程序每个分包的大小是 2M,总体积一共不能超过 24M。
- 抖音小程序每个分包的大小是 2M,总体积一共不能超过 16M(抖音小程序基础库 1.88.0 及以上版本开始支持,抖音小程序开发者工具请使用大于等于 2.0.6 且小于 3.0.0 的版本)。
- 快手小程序每个分包的大小是 2M,总体积一共不能超过 24M。
- 分包下支持独立的 static 目录,用来对静态资源进行分包。
- uni-app 内支持对微信小程序、QQ 小程序、百度小程序、支付宝小程序、抖音小程序(HBuilderX 3.0.3+)、快手小程序分包优化,即将静态资源或者 js 文件放入分包内不占用主包大小。
- 针对 vendor.js 过大的情况可以使用运行时压缩代码:HBuilderX 创建的项目勾选运行-->运行到小程序模拟器-->运行时是否压缩代码
使用方法:假设支持分包的 uni-app 目录结构如下
text
┌─pages
│ ├─index
│ │ └─index.vue
│ └─login
│ └─login.vue
├─pagesA
│ ├─static
│ └─list
│ └─list.vue
├─pagesB
│ ├─static
│ └─detail
│ └─detail.vue
├─static
├─main.js
├─App.vue
├─manifest.json
└─pages.json则需要在 pages.json 中填写
json
{
"pages": [{
"path": "pages/index/index",
"style": { ...}
}, {
"path": "pages/login/login",
"style": { ...}
}],
"subPackages": [{
"root": "pagesA",
"pages": [{
"path": "list/list",
"style": { ...}
}]
}, {
"root": "pagesB",
"pages": [{
"path": "detail/detail",
"style": { ...}
}]
}],
"preloadRule": {
"pagesA/list/list": {
"network": "all",
"packages": ["__APP__"]
},
"pagesB/detail/detail": {
"network": "all",
"packages": ["pagesA"]
}
}
}2. 打包
打包前一定要把历史包删除,否则可能遇到意想不到的错误
(1)小程序打包发布
1:在 manifest.json 中配置小程序 AppID,并开启 ES6 转 ES5 等功能
2:在微信公众平台,小程序中配置服务器域名白名单
3:点击发行按钮后,会在项目的目录 unpackage/dist/build/mp-weixin 生成微信小程序项目代码
4:在微信小程序开发者工具中,导入生成的微信小程序项目,点击微信开发工具的上传
(2)H5 打包
步骤一:在 manifest.json 进行 h5 配置,配置页面标题,index.html 模板、路由模式
步骤二:点击发行 -> 网站,H5 原生版
步骤三:根据导出的路径,将静态资源配置到服务器上

(3)App 打包
步骤一:在 manifest.json 进行基础配置,配置 AppID,如果没有的话就登录创建然后重新获取
步骤二:选择 App 图标配置,在自动生成图标下选择 logo,然后点击自动生成所有图标并替换
步骤三:App 启动界面配置,可以选择自定义启动图
步骤四:App 模块配置,点击需要用到的权限,比如用到了通讯录和地图,就勾选起来

步骤五:选择发行 -> 原生 App 云打包。选择 Android 包,还是 iOS 包,然后配置自有证书(自有证书企业用的,可使用公共测试证书,不过有下载次数限制)。点击打包。
步骤六:打包成功后,会返回一个地址,这时使用二维码生成器将地址转为二维码