在 uniapp 中创建项目
最常用的创建方式:通过 HBuilderX 可视化创建 (新手推荐)和 通过 CLI 命令行创建。
一、方式一:通过 HBuilderX 可视化创建(推荐新手)
这是最简单、最直观的方式,无需配置复杂的环境,适合入门。
步骤 1:安装 HBuilderX
- 访问 HBuilderX 官网
- 下载对应系统的安装包(选择「App 开发版」,包含 uniapp 开发所需的全部插件)
- 安装完成后打开 HBuilderX
步骤 2:创建 uniapp 项目
- 打开 HBuilderX 后,点击顶部菜单栏:
文件→新建→项目 - 在弹出的「新建项目」窗口中:
- 选择「uni-app」模板
- 填写「项目名称」(如
my-uniapp-project) - 选择「项目路径」(自定义保存位置)
- 选择模板(新手推荐「默认模板」,也可选择「Hello uni-app」示例模板)
- 取消勾选「创建 git 仓库」(新手可先不配置)
- 点击「创建」,等待项目初始化完成。
步骤 3:运行项目(验证创建成功)
- 选中左侧项目管理器中的新建项目
- 点击顶部菜单栏:
运行→运行到浏览器→ 选择任意浏览器(如 Chrome) - 浏览器会自动打开项目预览页面,看到 uniapp 默认页面即创建成功。
二、方式二:通过 CLI 命令行创建(适合有开发基础的用户)
这种方式需要先配置 Node.js 环境,适合习惯命令行操作的开发者。
步骤 1:准备环境
-
安装 Node.js(版本需 ≥ 12.0.0):
- 访问 Node.js 官网 下载并安装
- 验证安装:打开终端/命令提示符,输入
node -v和npm -v,能显示版本号即成功。
-
安装 uniapp 脚手架:
bashnpm install -g @vue/cli @dcloudio/vue-cli-plugin-uni
步骤 2:创建项目
-
打开终端,进入要创建项目的目录(如
cd ~/projects) -
执行创建命令:
bashvue create -p dcloudio/uni-preset-vue my-uniapp-project -
选择模板(上下箭头切换,回车确认):
default:默认模板(推荐新手)hello uni-app:示例模板(包含更多功能演示)
步骤 3:运行项目
-
进入项目目录:
bashcd my-uniapp-project -
运行到浏览器:
bashnpm run dev:h5 -
终端会输出访问地址(如
http://localhost:8080),打开即可预览。
补充说明
- 项目结构 :创建后的项目核心目录:
pages:存放页面文件(每个页面一个文件夹,包含.vue、json等文件)static:存放静态资源(图片、字体等)App.vue:项目根组件main.js:入口文件pages.json:页面路由配置
- 跨端运行 :除了 H5,还可运行到微信小程序、App 等:
- 运行到微信小程序:需先安装微信开发者工具,在 HBuilderX 中点击「运行 → 运行到小程序模拟器 → 微信开发者工具」
- 运行到 App:需安装对应平台的 SDK(如 Android SDK),在 HBuilderX 中点击「运行 → 运行到手机或模拟器」
组件
uniapp开发的核心部分「组件」相关知识,分为内置组件 (uniapp 原生提供)和自定义组件(开发者自己封装).
一、uniapp 内置组件(核心,直接用)
内置组件是 uniapp 封装好的、跨端兼容的基础组件,无需引入,直接在页面中使用,覆盖了开发中最常用的 UI 和功能场景。
1. 常用内置组件及用途
| 组件名 | 作用 | 简单示例 |
|---|---|---|
<view> |
基础布局容器(类似 HTML 的 div) | <view class="container">我是布局容器</view> |
<text> |
文本显示(仅支持文本内容) | <text selectable>可选中的文本</text>(selectable 支持长按选中) |
<button> |
按钮 | <button type="primary" @click="handleClick">主按钮</button> |
<image> |
图片展示 | <image src="/static/logo.png" mode="widthFix"></image>(mode 控制缩放) |
<input> |
输入框 | <input type="text" v-model="value" placeholder="请输入内容" /> |
<scroll-view> |
可滚动容器 | <scroll-view scroll-y style="height: 200px;">滚动内容</scroll-view> |
<swiper> |
轮播图 | 见下方完整示例 |
2. 内置组件使用示例(轮播图 <swiper>)
这是实际开发中常用的组件,直接复制到页面 .vue 文件中即可运行:
vue
<template>
<view>
<!-- 轮播图组件 -->
<swiper indicator-dots autoplay interval="3000" circular>
<!-- swiper-item 是 swiper 的子组件,每个轮播项 -->
<swiper-item>
<image src="/static/banner1.png" mode="widthFix" style="width: 100%;" />
</swiper-item>
<swiper-item>
<image src="/static/banner2.png" mode="widthFix" style="width: 100%;" />
</swiper-item>
</swiper>
</view>
</template>
<script>
export default {
data() {
return {};
}
};
</script>
关键属性说明:
indicator-dots:显示面板指示点autoplay:自动播放interval:自动切换时间间隔(毫秒)circular:循环播放
二、自定义组件(复用性强,重点)
当内置组件满足不了需求时,你可以封装自己的自定义组件,比如「自定义导航栏」「商品卡片」等,一次封装,多处复用。
步骤 1:创建自定义组件
- 在项目根目录新建
components文件夹(uniapp 约定的组件目录,自动识别); - 在
components下新建组件文件夹(如goods-card),再新建goods-card.vue文件。
步骤 2:编写自定义组件代码
以「商品卡片组件」为例,完整代码如下:
vue
<!-- components/goods-card/goods-card.vue -->
<template>
<view class="goods-card" @click="handleCardClick">
<!-- 商品图片 -->
<image :src="goodsImg" class="goods-img" />
<!-- 商品名称 -->
<text class="goods-name">{{ goodsName }}</text>
<!-- 商品价格 -->
<text class="goods-price">¥{{ goodsPrice }}</text>
</view>
</template>
<script>
export default {
// 组件名称(建议与文件名一致)
name: "goods-card",
// 接收父组件传递的参数(props 是组件的输入)
props: {
goodsImg: {
type: String,
required: true // 必填项
},
goodsName: {
type: String,
required: true
},
goodsPrice: {
type: Number,
required: true
}
},
methods: {
// 组件内部方法
handleCardClick() {
// 向父组件触发事件($emit 是组件的输出)
this.$emit("cardClick", { name: this.goodsName, price: this.goodsPrice });
}
}
};
</script>
<style scoped>
/* scoped 表示样式仅作用于当前组件,避免污染 */
.goods-card {
padding: 10px;
border-bottom: 1px solid #eee;
}
.goods-img {
width: 100%;
height: 200px;
}
.goods-name {
font-size: 14px;
margin: 5px 0;
display: block;
}
.goods-price {
color: #f00;
font-size: 16px;
font-weight: bold;
}
</style>
步骤 3:在页面中使用自定义组件
无需手动引入(uniapp 会自动扫描 components 目录),直接在页面 .vue 中使用:
vue
<!-- pages/index/index.vue -->
<template>
<view>
<!-- 使用自定义组件,传递 props 参数,监听事件 -->
<goods-card
:goodsImg="'/static/goods1.png'"
:goodsName="'苹果手机'"
:goodsPrice="5999"
@cardClick="handleGoodsClick"
/>
<goods-card
:goodsImg="'/static/goods2.png'"
:goodsName="'华为平板'"
:goodsPrice="2999"
@cardClick="handleGoodsClick"
/>
</view>
</template>
<script>
export default {
methods: {
// 接收子组件触发的事件
handleGoodsClick(data) {
console.log("点击了商品:", data);
// 可在此处跳转到商品详情页等操作
}
}
};
</script>
三、组件核心知识点补充
- props 传值:父组件向子组件传递数据,props 需声明类型、是否必填,保证数据规范;
- $emit 触发事件:子组件向父组件传递数据/通知父组件,是组件间通信的核心方式;
- scoped 样式 :给组件样式加
scoped,避免样式冲突,是自定义组件的最佳实践; - 组件复用:自定义组件可在多个页面/其他组件中使用,大幅提升开发效率;
- 跨端兼容:uniapp 组件会自动适配不同端(H5、小程序、App),无需单独修改。
总结
- uniapp 组件分为内置组件 (直接用,如
<view><swiper>)和自定义组件(封装复用逻辑); - 自定义组件核心是
props(接收父组件数据)和$emit(向父组件传值); - 自定义组件建议放在
components目录下,uniapp 自动识别,无需手动引入。
语法
你想系统了解 uniapp 的核心语法,基于 Vue 语法,同时扩展了跨端特有的语法规则,从「基础通用语法」和「uniapp 特有语法」两部分,用新手能看懂的方式讲清楚。
一、核心基础:uniapp 通用语法(基于 Vue 2/3)
uniapp 底层兼容 Vue 语法(主流是 Vue 2,也支持 Vue 3 + Vite),核心语法和 Vue 一致,先掌握这些就能完成大部分开发。
1. 模板语法(页面结构)
和 Vue 一样,uniapp 页面的 <template> 里写结构,支持插值、指令、事件绑定:
vue
<template>
<!-- 1. 插值表达式:显示变量 -->
<view>{{ msg }}</view>
<!-- 2. 指令:v-bind/v-if/v-for 等 -->
<view v-if="isShow">条件显示</view>
<view v-for="(item, index) in list" :key="index">
{{ index }} - {{ item.name }}
</view>
<!-- 3. 绑定属性:简写 : -->
<image :src="imgUrl" mode="widthFix"></image>
<!-- 4. 事件绑定:@ -->
<button @click="handleClick">点击按钮</button>
<!-- 5. 双向绑定:v-model(表单专用) -->
<input v-model="inputValue" placeholder="请输入内容" />
</template>
2. 脚本语法(逻辑处理)
<script> 里写页面逻辑,核心是 data、methods、生命周期 等:
vue
<script>
// Vue 2 写法(uniapp 主流)
export default {
// 页面名称
name: "IndexPage",
// 数据定义(响应式)
data() {
return {
msg: "Hello uniapp",
isShow: true,
list: [{ name: "苹果" }, { name: "香蕉" }],
imgUrl: "/static/logo.png",
inputValue: ""
};
},
// 生命周期(页面加载完成)
onLoad(options) {
// 页面初始化,可接收跳转参数
console.log("页面加载了", options);
},
// 方法定义
methods: {
handleClick() {
this.msg = "按钮被点击了";
// uniapp 内置 API:弹窗提示
uni.showToast({ title: "点击成功", icon: "success" });
}
}
};
</script>
3. 样式语法(页面样式)
<style> 里写样式,支持 CSS/SCSS,scoped 表示样式仅作用于当前页面:
vue
<style scoped>
/* 基础样式 */
view {
padding: 10px;
font-size: 14px;
}
/* 动态样式可结合插值 */
.button-active {
background-color: #007aff;
color: #fff;
}
/* 支持 rpx 单位(uniapp 适配各端的核心单位) */
.image {
width: 200rpx;
height: 200rpx;
}
</style>
关键:rpx 单位
uniapp 独创的适配单位,规定屏幕宽度为 750rpx,比如 iPhone 13 宽度 375px = 750rpx,1px = 2rpx,写 rpx 可自动适配不同屏幕。
二、uniapp 特有语法(跨端核心)
这是和纯 Vue 最大的区别,是 uniapp 实现跨端的关键,必须掌握:
1. 页面配置:pages.json
uniapp 没有 Vue 的路由文件,而是通过 pages.json 配置页面路由、导航栏、全局样式:
json
{
"pages": [
// 页面路由,第一项是首页
{
"path": "pages/index/index", // 页面路径
"style": {
"navigationBarTitleText": "首页", // 导航栏标题
"navigationBarBackgroundColor": "#fff", // 导航栏背景色
"enablePullDownRefresh": true // 开启下拉刷新
}
},
{
"path": "pages/detail/detail",
"style": {
"navigationBarTitleText": "详情页"
}
}
],
"globalStyle": {
// 全局样式(所有页面默认生效)
"navigationBarTextStyle": "black", // 导航栏文字颜色
"backgroundColor": "#f5f5f5" // 页面背景色
}
}
2. 生命周期:分「应用生命周期」和「页面生命周期」
uniapp 除了 Vue 的组件生命周期(created/mounted),还扩展了跨端的生命周期:
| 类型 | 常用生命周期 | 作用 |
|---|---|---|
| 应用生命周期 | onLaunch | 应用启动时触发(全局只执行一次) |
| 应用生命周期 | onShow | 应用前台显示时触发 |
| 页面生命周期 | onLoad | 页面加载时触发(接收跳转参数) |
| 页面生命周期 | onPullDownRefresh | 下拉刷新触发 |
| 页面生命周期 | onReachBottom | 上拉触底触发(加载更多) |
示例:应用生命周期(App.vue 中)
vue
<script>
export default {
onLaunch() {
console.log("App启动了");
},
onShow() {
console.log("App显示在前台");
}
};
</script>
3. 内置 API:uni.xxx()
uniapp 封装了跨端的 API,无需区分端(H5/小程序/App),直接调用:
javascript
// 1. 跳转页面(保留当前页,跳转到新页)
uni.navigateTo({
url: "/pages/detail/detail?id=123" // 传参
});
// 2. 关闭当前页,返回上一页
uni.navigateBack();
// 3. 发起网络请求(替代 axios)
uni.request({
url: "https://api.example.com/data",
method: "GET",
success: (res) => {
console.log("请求成功", res.data);
},
fail: (err) => {
console.log("请求失败", err);
}
});
// 4. 本地存储(替代 localStorage)
uni.setStorageSync("token", "123456"); // 同步存储
const token = uni.getStorageSync("token"); // 同步读取
4. 条件编译:跨端差异化开发
如果需要针对某一端(如微信小程序、H5)写差异化代码,用 //#ifdef 条件编译:
vue
<template>
<view>
<!-- 只在微信小程序显示 -->
<!-- #ifdef MP-WEIXIN -->
<button open-type="share">分享到微信</button>
<!-- #endif -->
<!-- 只在H5显示 -->
<!-- #ifdef H5 -->
<a href="/about">关于我们</a>
<!-- #endif -->
</view>
</template>
<script>
export default {
methods: {
handleClick() {
// 只在App端执行
// #ifdef APP-PLUS
uni.showActionSheet({
itemList: ["拍照", "从相册选择"],
success: (res) => console.log(res)
});
// #endif
}
}
};
</script>
常用条件编译标识:MP-WEIXIN(微信小程序)、H5(网页)、APP-PLUS(App)、MP-ALIPAY(支付宝小程序)。
三、语法核心注意事项
- uniapp 模板里只能有一个根节点 (必须用
<view>包裹所有内容); - 避免使用 Vue 的
window/document等浏览器 API,改用 uniapp 内置 API; - 小程序端有包体积限制,图片/静态资源尽量用网络地址,或压缩体积;
- 事件绑定优先用
@tap替代@click(小程序端更兼容)。
总结
- uniapp 基础语法和 Vue 高度一致,核心掌握「模板+脚本+样式」即可上手;
- 跨端核心是
pages.json(路由配置)、uni.xxx()(内置 API)、生命周期和条件编译; - 适配各端的关键是用
rpx单位、避免浏览器专属 API、用条件编译处理差异化逻辑。
核心指令
你想了解 uniapp 中常用的指令,这是编写 uniapp 页面结构的核心------uniapp 指令完全继承 Vue 核心指令,同时适配跨端场景,我会按「高频常用」「进阶实用」分类,结合 uniapp 实际开发场景讲解,每个指令都附具体示例。
一、uniapp 高频核心指令(必掌握)
这些指令覆盖 90% 的日常开发场景,适配所有端(H5/小程序/App)。
1. 插值表达式 {``{ }}(不是指令但最基础)
作用 :渲染页面数据(响应式),替代原生 JS 的 innerHTML。
uniapp 场景示例:
vue
<template>
<view>{{ nickname }}</view>
<view>{{ 1 + 2 }}</view> <!-- 支持简单表达式 -->
<view>{{ isLogin ? '已登录' : '未登录' }}</view> <!-- 三元运算 -->
</template>
<script>
export default {
data() {
return {
nickname: '张三',
isLogin: true
}
}
}
</script>
注意 :不能在属性上用 {``{ }},需用 v-bind。
2. 绑定属性 v-bind:(简写 :)
作用 :动态绑定标签属性(如 src、class、style、自定义属性)。
uniapp 高频场景:
vue
<template>
<!-- 1. 图片地址绑定(uniapp 静态资源/网络地址) -->
<image :src="avatarUrl" mode="widthFix"></image>
<!-- 2. 样式类绑定(条件切换) -->
<view :class="active ? 'active-class' : 'default-class'"></view>
<!-- 3. 内联样式绑定 -->
<view :style="{ fontSize: fontSize + 'rpx', color: textColor }"></view>
<!-- 4. 小程序专属属性绑定(如微信小程序的 open-type) -->
<button :data-id="goodsId" open-type="contact">联系客服</button>
</template>
<script>
export default {
data() {
return {
avatarUrl: '/static/avatar.png',
active: true,
fontSize: 14,
textColor: '#333',
goodsId: 123
}
}
}
</script>
3. 事件绑定 v-on:(简写 @)
作用 :绑定事件(点击、触摸、输入等),uniapp 优先用小程序兼容的事件名(如 tap 替代 click)。
uniapp 高频场景:
vue
<template>
<!-- 1. 点击事件(tap 比 click 更适配小程序) -->
<button @tap="handleTap">点击按钮</button>
<!-- 2. 传参 -->
<button @tap="handleDelete(123)">删除</button>
<!-- 3. 阻止事件冒泡(.stop) -->
<view @tap.stop="handleViewTap">
<button @tap="handleBtnTap">内部按钮</button>
</view>
<!-- 4. 输入框事件 -->
<input @input="handleInput" @blur="handleBlur" placeholder="请输入内容" />
</template>
<script>
export default {
methods: {
handleTap() {
uni.showToast({ title: '点击成功' });
},
handleDelete(id) {
console.log('删除ID:', id);
},
handleInput(e) {
console.log('输入内容:', e.detail.value); // 小程序/APP 用 e.detail.value 取值
},
handleBlur() {
console.log('输入框失焦');
}
}
}
</script>
关键 :uniapp 中输入框/表单的取值,优先用 e.detail.value(兼容小程序),而非 Vue 原生的 e.target.value。
4. 条件渲染 v-if / v-else-if / v-else
作用 :根据条件动态显示/隐藏元素(会销毁/重建 DOM,适合条件不频繁切换)。
uniapp 场景示例:
vue
<template>
<!-- 空数据提示 -->
<view v-if="list.length === 0">暂无数据</view>
<!-- 列表展示 -->
<view v-else v-for="(item, index) in list" :key="index">
{{ item.name }}
</view>
<!-- 登录状态切换 -->
<button v-if="!isLogin" @tap="goLogin">去登录</button>
<button v-else @tap="goUserCenter">我的中心</button>
</template>
<script>
export default {
data() {
return {
list: [],
isLogin: false
}
},
methods: {
goLogin() {},
goUserCenter() {}
}
}
</script>
5. 列表渲染 v-for
作用 :循环渲染列表,uniapp 中必须加 :key(推荐用唯一 ID,而非 index)。
uniapp 高频场景:
vue
<template>
<!-- 基础列表 -->
<view v-for="(item, index) in goodsList" :key="item.id">
<image :src="item.img" />
<text>{{ item.name }}</text>
<text>¥{{ item.price }}</text>
</view>
<!-- 嵌套循环 -->
<view v-for="(category, cIndex) in categoryList" :key="category.id">
<view>{{ category.name }}</view>
<view v-for="(goods, gIndex) in category.goods" :key="goods.id">
{{ goods.name }}
</view>
</view>
</template>
<script>
export default {
data() {
return {
goodsList: [
{ id: 1, img: '/static/g1.png', name: '苹果', price: 9.9 },
{ id: 2, img: '/static/g2.png', name: '香蕉', price: 5.9 }
],
categoryList: [
{ id: 1, name: '水果', goods: [{ id: 101, name: '草莓' }] }
]
}
}
}
</script>
注意:
:key必须是唯一值(如 ID),避免用 index(列表重排时会出问题);- 小程序端
v-for嵌套不建议超过 2 层(影响性能)。
6. 双向绑定 v-model
作用 :表单元素(输入框、选择器等)和数据双向同步,uniapp 适配了小程序的表单组件。
uniapp 高频场景:
vue
<template>
<!-- 输入框 -->
<input v-model="username" placeholder="请输入用户名" />
<!-- 多选框 -->
<checkbox v-model="checked" />
<!-- 小程序 picker 选择器(uniapp 兼容) -->
<picker mode="selector" :range="cityList" v-model="cityIndex">
<view>当前选择:{{ cityList[cityIndex] }}</view>
</picker>
</template>
<script>
export default {
data() {
return {
username: '',
checked: false,
cityList: ['北京', '上海', '广州'],
cityIndex: 0
}
}
}
</script>
注意 :uniapp 中 v-model 兼容所有端,但小程序的特殊表单组件(如 picker)需结合组件自身属性使用。
二、uniapp 进阶实用指令
1. 条件显示 v-show
作用 :根据条件显示/隐藏元素(只是修改 display 样式,不销毁 DOM,适合频繁切换)。
示例:
vue
<view v-show="isShow">频繁切换的提示语</view>
对比 v-if :v-if 是"销毁/重建",v-show 是"显示/隐藏",高频切换用 v-show 更高效。
2. 一次性渲染 v-once
作用 :元素只渲染一次,后续数据变化不再更新(适合静态内容,优化性能)。
uniapp 场景:页面底部的版权信息、固定文案。
vue
<view v-once>©2026 某某科技 保留所有权利</view>
3. 文本渲染 v-text / v-html
v-text:等价于{``{ }},渲染纯文本(避免 XSS);v-html:渲染富文本(仅 H5 端支持,小程序/App 需用富文本组件rich-text)。
示例:
vue
<view v-text="desc"></view>
<!-- 仅 H5 可用 -->
<view v-html="richDesc"></view>
<!-- 跨端富文本推荐用 rich-text -->
<rich-text :nodes="richDesc"></rich-text>
三、uniapp 指令使用注意事项
- 小程序端不支持
v-html,需替换为<rich-text>组件; v-for优先级高于v-if,若需条件循环,建议先在外层用v-if判断,再内层v-for;- 避免在
v-for中直接修改数据(会导致视图更新异常); - uniapp 中无
v-cloak指令(小程序无 DOM 加载问题),无需使用。
总结
- uniapp 指令核心继承 Vue,高频指令为:
{``{ }}、:bind、@on、v-if/v-else、v-for、v-model; - 跨端适配关键:事件用
tap替代click、表单取值用e.detail.value、富文本用rich-text替代v-html; - 性能优化:频繁切换用
v-show,静态内容用v-once,v-for必须加唯一:key。
代码打包
你想知道在 uniapp 中如何将项目分别打包成 APP 和 小程序(以微信小程序为例),这是 uniapp 实现跨端交付的核心步骤,我会分两大场景,一步步教你完整的打包流程,包括前置准备、打包操作、常见问题解决。
一、打包生成微信小程序(最常用)
前置准备
- 注册微信小程序账号 :
- 访问 微信公众平台 注册账号,完成主体认证(个人/企业);
- 记录小程序的 AppID(登录后在「开发管理 → 开发设置」中查看),不要用测试 AppID。
- 安装微信开发者工具 :
- 下载 微信开发者工具,安装后登录(绑定小程序账号)。
打包步骤(以 HBuilderX 为例)
步骤 1:配置小程序 AppID
- 打开 HBuilderX,找到你的 uniapp 项目,根目录新建/编辑
manifest.json文件; - 点击「微信小程序配置」选项卡:
- 勾选「微信小程序」;
- 填写「小程序 AppID」(替换默认的测试 ID);
- 可选:配置「小程序名称」「类目」等。
步骤 2:发行/打包小程序
- 点击 HBuilderX 顶部菜单栏:
发行→小程序-微信; - 在弹出的窗口中:
- 选择「微信开发者工具路径」(自动识别或手动选择安装路径);
- 勾选「是否压缩代码」(建议勾选,减小体积);
- 点击「发行」,等待打包完成。
步骤 3:预览与上传
- 打包完成后,会自动打开微信开发者工具并加载项目;
- 预览验证:
- 在微信开发者工具中点击「预览」,用手机扫码查看效果,检查功能是否正常;
- 若有报错(如「包体积过大」「接口未配置域名」),先修复问题。
- 上传代码:
- 确认无误后,点击「上传」,填写版本号(如 1.0.0)和备注;
- 上传成功后,回到微信公众平台「开发管理 → 版本管理」,可看到「开发版本」,提交审核即可。
小程序打包注意事项
- 包体积限制 :微信小程序主包不能超过 2MB,分包总计不超过 20MB;
- 优化:将图片/静态资源放到服务器(不要放本地)、开启代码压缩、使用分包加载;
- 域名配置:小程序请求的接口域名需在微信公众平台「开发管理 → 服务器域名」中配置,否则无法请求;
- 特殊 API 适配 :如支付、分享等,需在
manifest.json中配置对应权限,且接口需符合微信规范。
二、打包生成 APP(Android/iOS)
前置准备
1. 基础环境(新手推荐 HBuilderX 云端打包,无需本地配置)
- 若用「云端打包」:无需安装 Android/iOS 编译环境,只需注册 DCloud 账号(HBuilderX 内置登录入口);
- 若用「本地打包」(进阶):
- Android:安装 JDK、Android SDK,配置环境变量;
- iOS:需 Mac 电脑 + Xcode,且有苹果开发者账号。
2. 申请 App 证书(关键)
- Android 证书 :
- 方式 1(推荐):HBuilderX 内置生成工具 → 点击
发行→原生App-云打包→ 「证书管理」→ 「新建证书」,自动生成安卓证书(记录证书密码、别名); - 方式 2:手动用 keytool 命令生成(适合进阶)。
- 方式 1(推荐):HBuilderX 内置生成工具 → 点击
- iOS 证书 :
- 需苹果开发者账号(年费 99 美元),在苹果开发者后台申请「开发证书/发布证书」「描述文件」,导入 HBuilderX。
打包步骤(云端打包,新手推荐)
步骤 1:配置 APP 信息
- 打开项目的
manifest.json文件,点击「App 配置」选项卡:- 填写「应用名称」「应用图标」「启动页」(可上传图片自动生成适配尺寸);
- 配置「包名」(Android:如 com.xxx.app;iOS:如 com.xxx.xxx,需唯一);
- 填写「版本号」「版本名称」。
步骤 2:发起云端打包
- 点击 HBuilderX 顶部菜单栏:
发行→原生App-云打包; - 在打包窗口中:
- 选择打包平台:「Android」(必选)、「iOS」(需配置证书);
- 选择证书:Android 选择之前生成的证书,iOS 导入苹果证书;
- 可选配置:是否打测试包、是否开启混淆、配置第三方 SDK(如推送、支付);
- 点击「打包」,等待云端编译(约 5-10 分钟,可在「DCloud 开发者中心」查看进度)。
步骤 3:下载与测试
- 打包完成后,会生成下载链接(Android 是
.apk文件,iOS 是.ipa文件); - 测试:
- Android:将
.apk文件发送到安卓手机,安装后测试功能、性能、兼容性; - iOS:
- 测试包:用 TestFlight 或 Xcode 安装到测试机;
- 正式包:上传到 App Store Connect,提交审核。
- Android:将
APP 打包注意事项
- Android 兼容性:建议选择最低兼容版本为 Android 5.0+,覆盖 99% 设备;
- 权限配置 :如相机、定位、存储等权限,需在
manifest.json中「App 权限配置」里勾选,否则功能无法使用; - 包体积优化:移除无用插件、压缩图片、关闭不必要的模块(如地图、支付);
- iOS 审核:需符合 App Store 审核规则(如隐私政策、功能合规),避免审核被拒。
三、通用打包优化建议
- 代码检查 :打包前运行
运行 → 运行到模拟器测试,修复控制台报错(如未定义变量、接口请求失败); - 资源清理:删除项目中未使用的图片、页面、组件,减小包体积;
- 配置检查 :确认
manifest.json中各端配置(AppID、权限、域名)正确; - 测试覆盖:至少测试核心功能(如登录、支付、跳转、表单提交)。
总结
- 小程序打包:核心是配置微信 AppID → 发行打包 → 微信开发者工具上传 → 公众平台审核,重点注意包体积和域名配置;
- APP 打包 :新手优先用 HBuilderX 云端打包,只需配置证书和
manifest.json,等待云端编译即可,iOS 需额外准备苹果开发者账号; - 打包前务必完成功能测试和资源优化,避免因配置错误或包体积问题导致打包失败/审核被拒。
小程序分包相关事宜
你想了解 uniapp 中小程序分包加载的具体配置方法,这是解决微信小程序主包体积超限(2MB)的核心方案,我会从「分包原理」「配置步骤」「实战示例」「注意事项」四个维度,手把手教你配置,确保新手也能快速上手。
一、先理解分包核心逻辑
- 主包:默认包含首页、tabBar 页面及公共资源,体积≤2MB;
- 分包:将非核心页面(如详情页、个人中心、订单页)拆分成独立包,总计≤20MB;
- 加载规则:打开分包页面时才下载对应分包,不影响主包启动速度。
uniapp 支持两种分包方式:
- 普通分包:手动指定页面归属哪个分包;
- 独立分包:可独立运行的分包(无需下载主包,如活动页),优先级更高。
二、普通分包配置步骤(最常用)
步骤 1:规划分包结构
先梳理项目页面,将非核心页面归类到分包目录,推荐目录结构:
pages(主包)
├── index(首页,主包)
├── tabbar(tabBar页面,主包)
pages-sub(分包目录,自定义名称)
├── goods(商品相关分包)
│ ├── detail(商品详情)
│ ├── list(商品列表)
├── order(订单相关分包)
│ ├── pay(支付页)
│ ├── record(订单记录)
步骤 2:修改 pages.json 配置
核心是在 pages.json 中新增 subPackages 字段,配置分包路径和页面:
json
{
"pages": [
// 主包页面(首页、tabBar页必须放主包)
{
"path": "pages/index/index",
"style": { "navigationBarTitleText": "首页" }
},
{
"path": "pages/tabbar/home/home",
"style": { "navigationBarTitleText": "首页Tab" }
}
],
"subPackages": [
// 第一个分包:商品分包
{
"root": "pages-sub/goods", // 分包根目录(自定义)
"pages": [
// 分包内的页面(路径相对于 root)
{
"path": "detail/detail", // 完整路径:pages-sub/goods/detail/detail
"style": { "navigationBarTitleText": "商品详情" }
},
{
"path": "list/list", // 完整路径:pages-sub/goods/list/list
"style": { "navigationBarTitleText": "商品列表" }
}
]
},
// 第二个分包:订单分包
{
"root": "pages-sub/order",
"pages": [
{
"path": "pay/pay",
"style": { "navigationBarTitleText": "支付页面" }
},
{
"path": "record/record",
"style": { "navigationBarTitleText": "订单记录" }
}
]
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarBackgroundColor": "#fff"
}
}
步骤 3:页面跳转(分包页面跳转)
跳转分包页面的方式和主包完全一致,uniapp 会自动处理分包加载:
javascript
// 跳转商品详情页(分包页面)
uni.navigateTo({
url: "/pages-sub/goods/detail/detail?id=123"
});
// 跳转订单支付页(分包页面)
uni.navigateTo({
url: "/pages-sub/order/pay/pay?orderId=456"
});
三、独立分包配置(进阶)
独立分包无需依赖主包,可单独访问(如活动页、推广页),适合需要快速打开的页面。
配置方法:在分包中加 independent: true
json
{
"pages": [/* 主包页面 */],
"subPackages": [
// 独立分包:活动页
{
"root": "pages-sub/activity",
"independent": true, // 标记为独立分包
"pages": [
{
"path": "promotion/promotion",
"style": { "navigationBarTitleText": "618活动" }
}
]
},
// 普通分包
{
"root": "pages-sub/goods",
"pages": [/* 普通分包页面 */]
}
]
}
四、分包优化:预加载分包
提前加载常用分包(如进入首页后预加载商品分包),避免用户点击时等待下载:
在 pages.json 中新增 preloadRule 字段:
json
{
"pages": [/* 主包页面 */],
"subPackages": [/* 分包配置 */],
// 预加载规则
"preloadRule": {
// 当打开首页(主包页面)时,预加载商品分包
"pages/index/index": {
"network": "all", // all:所有网络都预加载,wifi:仅wifi下预加载
"packages": ["pages-sub/goods"] // 要预加载的分包根目录
},
// 打开商品列表页时,预加载订单分包
"pages-sub/goods/list/list": {
"network": "wifi",
"packages": ["pages-sub/order"]
}
}
}
五、关键注意事项
- 主包体积限制 :主包仍需≤2MB,需将大资源(图片、视频)放到服务器,不要放在主包
static目录; - 公共资源处理 :
- 主包和分包共享的组件/静态资源,放在主包
components/static目录; - 仅分包使用的资源,放在分包目录下(如
pages-sub/goods/static);
- 主包和分包共享的组件/静态资源,放在主包
- tabBar 页面必须在主包:tabBar 配置的页面不能放在分包中,否则报错;
- 路径不要写错 :跳转分包页面时,路径要写完整(如
/pages-sub/goods/detail/detail),不要省略根目录; - 分包数量限制:微信小程序最多支持 20 个分包;
- 调试查看体积:在微信开发者工具中,点击「详情 → 基本信息 → 代码包大小」,可查看主包/分包体积。
六、常见问题解决
- 分包后仍提示主包过大 :
- 检查主包是否包含大图片/视频,移到服务器;
- 检查是否有未使用的页面/组件,删除后重新打包;
- 开启代码压缩(HBuilderX 打包时勾选「压缩代码」)。
- 跳转分包页面报错「页面不存在」 :
- 检查
pages.json中分包路径是否正确; - 检查跳转 url 是否写全(需包含分包根目录)。
- 检查
总结
- 普通分包核心是在
pages.json中配置subPackages,将非核心页面归类到分包目录; - 独立分包只需加
independent: true,可脱离主包运行; - 预加载分包(
preloadRule)能优化用户体验,避免跳转等待; - 核心禁忌:tabBar 页面必须在主包,主包体积≤2MB,路径配置要完整。
分包完整示例
这是一份可直接复制使用的 uniapp 小程序分包配置完整示例(包含普通分包、独立分包、预加载规则),你只需替换成自己的页面路径和名称,就能快速完成分包配置。
json
{
"pages": [
// 主包页面:首页、tabBar页面必须放在主包
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首页",
"enablePullDownRefresh": true
}
},
{
"path": "pages/tabbar/home/home",
"style": {
"navigationBarTitleText": "首页Tab",
"navigationBarBackgroundColor": "#ffffff"
}
},
{
"path": "pages/tabbar/mine/mine",
"style": {
"navigationBarTitleText": "我的"
}
}
],
// tabBar配置(仅示例,需根据自己项目调整)
"tabBar": {
"color": "#666666",
"selectedColor": "#007aff",
"backgroundColor": "#ffffff",
"borderStyle": "black",
"list": [
{
"pagePath": "pages/tabbar/home/home",
"text": "首页",
"iconPath": "static/tabbar/home.png",
"selectedIconPath": "static/tabbar/home-active.png"
},
{
"pagePath": "pages/tabbar/mine/mine",
"text": "我的",
"iconPath": "static/tabbar/mine.png",
"selectedIconPath": "static/tabbar/mine-active.png"
}
]
},
// 分包核心配置
"subPackages": [
// 普通分包1:商品相关(非tabBar页面)
{
"root": "pages-sub/goods", // 分包根目录
"pages": [
{
"path": "detail/detail", // 完整路径:pages-sub/goods/detail/detail
"style": {
"navigationBarTitleText": "商品详情",
"enablePullDownRefresh": false
}
},
{
"path": "list/list", // 完整路径:pages-sub/goods/list/list
"style": {
"navigationBarTitleText": "商品列表"
}
},
{
"path": "category/category", // 完整路径:pages-sub/goods/category/category
"style": {
"navigationBarTitleText": "商品分类"
}
}
]
},
// 普通分包2:订单相关
{
"root": "pages-sub/order",
"pages": [
{
"path": "pay/pay",
"style": {
"navigationBarTitleText": "订单支付"
}
},
{
"path": "record/record",
"style": {
"navigationBarTitleText": "订单记录"
}
},
{
"path": "refund/refund",
"style": {
"navigationBarTitleText": "退款申请"
}
}
]
},
// 独立分包:活动页(可脱离主包运行)
{
"root": "pages-sub/activity",
"independent": true, // 标记为独立分包
"pages": [
{
"path": "promotion/promotion",
"style": {
"navigationBarTitleText": "618特惠活动"
}
},
{
"path": "coupon/coupon",
"style": {
"navigationBarTitleText": "优惠券领取"
}
}
]
}
],
// 分包预加载规则(优化用户体验)
"preloadRule": {
// 打开首页时,预加载商品分包(所有网络环境)
"pages/index/index": {
"network": "all", // all/wifi,建议非核心分包用wifi
"packages": ["pages-sub/goods"] // 要预加载的分包根目录
},
// 打开商品列表页时,预加载订单分包(仅wifi)
"pages-sub/goods/list/list": {
"network": "wifi",
"packages": ["pages-sub/order"]
},
// 独立分包无需预加载(本身独立运行)
"pages-sub/activity/promotion/promotion": {
"network": "wifi",
"packages": ["pages-sub/goods"] // 活动页跳转商品页时预加载
}
},
// 全局样式配置
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarBackgroundColor": "#f5f5f5",
"backgroundColor": "#f5f5f5",
"navigationBarTitleText": "我的小程序",
"backgroundTextStyle": "light"
},
// 其他全局配置(按需添加)
"lazyCodeLoading": "requiredComponents" // 按需加载组件,减小体积
}
配置使用说明(新手必看)
-
目录结构对应 :
配置文件中的
root和path需和实际项目目录一致,建议按以下结构创建:├── pages(主包) │ ├── index │ └── tabbar ├── pages-sub(分包根目录) │ ├── goods(商品分包) │ │ ├── detail │ │ ├── list │ │ └── category │ ├── order(订单分包) │ └── activity(独立分包) ├── static(主包公共资源) └── pages.json(当前配置文件) -
页面跳转示例 :
复制以下代码到按钮点击事件中,即可跳转对应分包页面:
javascript// 跳转普通分包(商品详情) goGoodsDetail() { uni.navigateTo({ url: "/pages-sub/goods/detail/detail?id=123" // 路径要写完整 }); }, // 跳转独立分包(优惠券) goCoupon() { uni.navigateTo({ url: "/pages-sub/activity/coupon/coupon" }); } -
体积检查 :
配置完成后,打包到微信开发者工具,点击「详情 → 基本信息 → 代码包大小」,可查看:
- 主包体积是否 ≤2MB
- 各分包体积是否合理
总结
- 这份配置包含 普通分包、独立分包、预加载 核心功能,可直接替换页面路径使用;
- 核心规则:tabBar 页面必须在主包,独立分包加
independent: true,预加载用preloadRule; - 跳转分包页面时,url 需写完整路径(包含分包根目录),避免页面不存在报错。