HBuilder实现uniapp微信小程序项目到发布(超级详细)
本文详细介绍了微信小程序开发的全流程。从开发环境搭建(HBuilderX、微信开发者工具)、项目初始化配置(manifest.json/pages.json),到核心功能实现:包括网络请求封装(环境变量配置、请求拦截与响应处理)、状态管理(Pinia)、UI框架引入(uViewPlus)。最后讲解了小程序发布流程(编译、上传、审核、发布)。重点突出了微信小程序特有的配置项(AppID、域名白名单)
一、开发前的准备
1、工具准备:
HBuilderx、微信开发者工具。
2、申请微信小程序,获取appid
微信公众平台:https://mp.weixin.qq.com/
进入微信公众平台-> 点击立即注册-> 点击小程序-> 点击前往注册



注册好后,扫码登陆平台,找到AppID,作为绑定开发者工具用(注意不要暴露,使用在后文)

或

二、新建项目
打开hbuilder编辑器选择文件->新建->项目


试运行:
可能会出现没有配置微信开发工具情况,此时需要配置微信开发者工具路径
注:若遇到这种情况,只需打开某个项目文件即可



注:若不配置这个路径,HBuilderx也会智能查找到对应路径,若查找不到就需要手动配置。
配置微信开发者工具:
打开微信开发者工具>设置>安全设置>开启服务端口


运行:
打开HBuilderx>运行>运行到小程序模拟器>微信开发者工具

运行成功:

三、项目结构

| 文件名 | 用途 |
|---|---|
| pages | 用于放置页面文件 |
| static | 静态文件位置 |
| App.vue | 同vue |
| main.js | 同vue |
| manifest.json | 项目配置(下文详讲) |
| pages.json | 页面配置(下文详讲) |
| uni.scss | 全局样式文件 |
3.1 manifest.json配置
此文主要用于开发微信小程序,其他的配置可以暂时不管,选择微信小程序配置。核心认知:两个不同的 AppID

注:这里的基础配置的appid不用设置保持为空即可,这里的appid是 DCloud 提供的应用标识,完全不影响开发和调试微信小程序。

|
配置项 |
是否需设置 |
作用说明 |
|---|---|---|
|
微信小程序AppID |
必须 |
这是小程序的唯一身份标识。必须从微信公众平台申请获取。 不填写将无法正常上传发布,也无法使用部分需要真机调试的API。 学习阶段可先使用测试号。 |
|
ES6转ES5 |
推荐开启 |
将项目中的ES6及以上版本的JavaScript语法转换为兼容性更好的ES5语法, 以确保小程序在更多旧版本微信环境中能稳定运行。 |
|
上传代码时样式自动补全 |
推荐开启 |
在上传代码前,自动补全CSS样式(如添加 解决不同平台下的样式兼容性问题。 |
|
上传代码时自动压缩 |
推荐开启 |
压缩JS/CSS代码,确保不超过微信2MB限制 |
|
检查安全域名和TLS版本 |
可选 |
检查API域名是否在微信后台配置,避免线上请求失败 |
|
位置接口 |
按需开启 |
如果您的小程序需要获取用户地理位置信息(例如地图、外卖、打车应用),则必须勾选此项。它会在小程序配置中声明 |
|
uniPush2.0 |
按需开启 |
如果您需要使用DCloud提供的、支持全端(App、小程序、Web)的统一推送服务,则需勾选并配置此项。 |
|
开启云端一体安全网络 |
按需开启 |
防止抓包、数据加密,适合金融等高安全场景 |
3.2 pages.json
pages.json是 uni-app 的全局配置文件。
页面路径 - 有哪些页面,怎么访问。
全局样式 - 导航栏颜色、标题文字等。
TabBar - 底部/顶部导航栏。
组件引入 - 自动导入规则。
开发模式 - 直达页面的启动方式。
1、核心配置项速查表
|
配置项 |
作用一句话说明 |
注意点 |
|---|---|---|
|
|
定义所有页面路径,第一项为首页 |
增删页面必须修改此数组 |
|
|
设置所有页面的导航栏、背景色等 |
会被页面单独样式覆盖 |
|
|
配置底部/顶部选项卡导航 |
最少2个,最多5个Tab |
|
|
开启组件自动导入,无需 |
开发效率神器 |
|
|
开发期间模拟直达页面场景 |
仅开发环境生效 |
pages - 页面路由配置
{
"pages": [
{
"path": "pages/index/index", // 页面路径(第一项是首页)
"style": { // 页面单独样式,覆盖全局
"navigationBarTitleText": "首页",
"navigationBarBackgroundColor": "#007AFF"
}
},
{
"path": "pages/user/user", // 第二个页面
"style": {
"navigationBarTitleText": "我的"
}
}
]
}
🚨 重要规则:
-
路径不需要写后缀(
.vue),框架自动查找 -
新增/删除页面必须修改此数组
-
页面顺序即显示顺序
globalStyle - 全局窗口样式
{
"globalStyle": {
// 导航栏配置
"navigationBarBackgroundColor": "#007AFF", // 背景色
"navigationBarTextStyle": "white", // 文字颜色:black/white
"navigationBarTitleText": "我的小程序", // 标题文字
// 下拉刷新
"enablePullDownRefresh": false, // 是否开启下拉刷新
"backgroundTextStyle": "dark", // loading样式:dark/light
"backgroundColor": "#FFFFFF", // 下拉窗口背景色
// 上拉触底
"onReachBottomDistance": 50, // 距离底部多少px触发
"backgroundColorTop": "#FFFFFF", // 顶部背景色
"backgroundColorBottom": "#F8F8F8" // 底部背景色
}
}
tabBar - 底部导航栏
{
"tabBar": {
"color": "#7A7E83", // 默认文字颜色
"selectedColor": "#007AFF", // 选中时文字颜色
"backgroundColor": "#FFFFFF", // 背景色
"borderStyle": "black", // 上边框颜色
"position": "bottom", // 位置:bottom(默认) / top(仅微信)
"list": [
{
"pagePath": "pages/index/index", // 页面路径(必须在pages中定义)
"text": "首页", // 显示文字
"iconPath": "static/tabbar/home.png", // 默认图标
"selectedIconPath": "static/tabbar/home-active.png" // 选中图标
},
{
"pagePath": "pages/user/user",
"text": "我的",
"iconPath": "static/tabbar/user.png",
"selectedIconPath": "static/tabbar/user-active.png"
}
]
}
}
📌 注意事项:
|
项目 |
要求/限制 |
|---|---|
|
Tab数量 |
最少2个,最多5个 |
|
图标大小 |
建议 81px × 81px,不超过40KB |
|
图标格式 |
不支持网络图片,不支持字体图标(可用iconfont) |
|
位置限制 |
|
个性化配置 - 中间凸起按钮
{
"tabBar": {
"list": [
// ... 其他tab(必须为偶数个,如2个或4个)
],
"midButton": {
"width": "80px", // 按钮宽度
"height": "60px", // 高度(可大于tabBar实现凸起)
"text": "发布", // 文字
"iconPath": "static/tabbar/add.png", // 图标路径
"backgroundImage": "static/tabbar/bg.png", // 背景图
"iconfont": { // 字体图标(优先级高于iconPath)
"text": "\ue60d", // 字体图标unicode
"selectedText": "\ue60e", // 选中时图标
"fontSize": "20px", // 图标大小
"color": "#FFFFFF", // 默认颜色
"selectedColor": "#007AFF" // 选中颜色
}
}
}
}
🚨 重要提示:
-
仅当
list有偶数个Tab时才生效 -
平台限制:仅支持 App(2.3.4+) 和 H5(3.0.0+)
-
无pagePath:需手动监听点击事件
-
交互实现:
// 在需要监听的文件中
export default {
onTabItemTap(e) {
console.log('点击了Tab:', e.index)
if (e.index === 1) { // 假设中间按钮是第二个
uni.navigateTo({
url: '/pages/publish/publish'
})
}
}
}
condition - 开发启动模式
作用:开发阶段模拟特定场景(如分享后打开的页面)
{
"condition": {
"current": 0, // 当前激活的模式索引
"list": [
{
"name": "商品详情页", // 模式名称
"path": "pages/product/detail", // 页面路径
"query": "id=123&type=1" // 页面参数
},
{
"name": "活动页面",
"path": "pages/activity/index",
"query": "activityId=888"
}
]
}
}
使用方法:
-
配置
condition后保存 -
微信开发者工具 → 编译模式 → 选择配置的模式
-
点击"编译"即可直达对应页面
完整示例:
{
// 1. 页面配置
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首页",
"enablePullDownRefresh": true
}
},
{
"path": "pages/category/category",
"style": {
"navigationBarTitleText": "分类"
}
},
{
"path": "pages/cart/cart",
"style": {
"navigationBarTitleText": "购物车"
}
},
{
"path": "pages/user/user",
"style": {
"navigationBarTitleText": "我的"
}
}
],
// 2. 全局样式
"globalStyle": {
"navigationBarBackgroundColor": "#007AFF",
"navigationBarTextStyle": "white",
"navigationBarTitleText": "商城小程序",
"backgroundColor": "#F8F8F8",
"backgroundTextStyle": "dark"
},
// 3. 底部导航
"tabBar": {
"color": "#999999",
"selectedColor": "#FF5F15",
"backgroundColor": "#FFFFFF",
"borderStyle": "white",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "static/tabbar/home.png",
"selectedIconPath": "static/tabbar/home-active.png"
},
{
"pagePath": "pages/category/category",
"text": "分类",
"iconPath": "static/tabbar/category.png",
"selectedIconPath": "static/tabbar/category-active.png"
},
{
"pagePath": "pages/cart/cart",
"text": "购物车",
"iconPath": "static/tabbar/cart.png",
"selectedIconPath": "static/tabbar/cart-active.png"
},
{
"pagePath": "pages/user/user",
"text": "我的",
"iconPath": "static/tabbar/user.png",
"selectedIconPath": "static/tabbar/user-active.png"
}
]
},
// 4. 组件自动导入
"easycom": {
"autoscan": true,
"custom": {
"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue",
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
}
},
// 5. 开发模式
"condition": {
"current": 0,
"list": [
{
"name": "商品详情",
"path": "pages/product/detail",
"query": "id=1001"
}
]
}
}
2、主要子配置项速查表
|
父配置项 |
子配置项 |
作用 |
|---|---|---|
|
|
|
页面路径,例如 |
|
|
单独设置该页面的样式,会覆盖全局样式。 |
|
|
|
|
导航栏标题文字(如“首页”)。 |
|
|
导航栏背景颜色(如"#007AFF")。 |
|
|
|
是否开启全局下拉刷新。 |
|
|
onReachBottomDistance |
页面上拉触底事件,触发时距页面底部距离,单位只支持px |
|
|
backgroundColor |
下拉显示出来的窗口的背景色 |
|
|
backgroundTextStyle |
下拉 loading 的样式,仅支持 dark / light |
|
|
|
|
Tab 列表,至少2个,最多5个。 |
|
|
Tab对应页面路径,必须在 |
|
|
|
Tab上显示的文字(如“首页”)。 |
|
|
|
Tab的图标路径。 |
四、封装网络请求
4.1配置环境变量
在src目录下新建env文件夹,src/env/index.js
//主要作用是标识当前项目的平台或服务提供商是「微信」
export const provider = 'weixin'
// #ifdef MP-WEIXIN
export const env = __wxConfig.envVersion//获取当前微信小程序的运行版本
//根据不同的环境,自动选择不同的服务器地址
export const BASE_URL = {
develop: 'https://xxxx.xxxxxdev.com',//开发环境版本,匹配到这个
trial: 'https://xxxx.xxxxxsit.com',//测试环境版本
release: 'https://xxxx.xxxxx.com'//正式环境版本
}[env]//相当于读取 obj['develop']
//假设env = 'develop'
export const BASE_API_URL = BASE_URL + '/api'//加上统一的API接口前缀,拼接成完成的url地址
export const APPID = 'xxxxxxxxx'//集中管理微信小程序的身份证(AppID)
// #endif
注:条件编译语句解释
|
部分 |
含义 |
说明 |
|---|---|---|
|
|
注释符号 |
在普通的JavaScript中,这行代码会被当做注释忽略掉。 |
|
|
条件编译指令 |
意思是 "if defined"(如果定义了)。这是uni-app提供的特殊语法。 |
|
|
平台标识 |
特指微信小程序平台(Mini Program - Weixin)。 |
常用平台标识符
|
标识 |
平台 |
|---|---|
|
|
微信小程序 |
|
|
支付宝小程序 |
|
|
百度小程序 |
|
|
Web浏览器(H5) |
|
|
App |
|
|
抖音/头条小程序 |
4.2封装请求
在src目录下新建stores文件夹,src/stores/user.js
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
// 用户状态管理
export const useUserStore = defineStore('userStore', () => {
// 用户数据(从本地存储读取)
const globalUser = ref(JSON.parse(uni.getStorageSync('user') || '{}'))
// 计算属性
const access_token = computed(() => globalUser.value.access_token) // 访问token
const refresh_token = computed(() => globalUser.value.refresh_token) // 刷新token
const hasLogin = computed(() => !!globalUser.value.access_token) // 登录状态
const userId = computed(() => globalUser.value.user_id || null) // 用户ID
// 设置用户信息(自动保存到本地)
const setGlobalUser = (val) => {
globalUser.value = val
uni.setStorageSync('user', JSON.stringify(val))
}
// 更新用户信息(合并更新)
const updateGlobalUser = (obj) => {
setGlobalUser({ ...globalUser.value, ...obj })
}
// 退出登录(清空数据)
const loginOut = () => {
globalUser.value = {}
uni.clearStorageSync('user')
}
// 暴露给组件使用
return {
globalUser, // 用户数据
access_token, // 访问token
refresh_token, // 刷新token
hasLogin, // 是否登录
userId, // 用户ID
setGlobalUser, // 设置用户
updateGlobalUser, // 更新用户
loginOut // 退出登录
}
})
在src目录下新建utils文件夹,src/utils/index.js
import { useUserStore } from '@/stores/user'
import { provider } from '@/env'
// 将uni-app回调API转为Promise
const createUniAPI = (method) => {
return (options = {}) => {
return new Promise((resolve, reject) => {
uni[method]({
provider, // 平台配置
...options, // 用户参数
success: resolve, // 成功回调
fail: reject // 失败回调
})
})
}
}
// Promise化的常用API
export const uniRequest = createUniAPI('request') // 网络请求
export const uniGetStorage = createUniAPI('getStorage') // 读取存储
export const uniSetStorage = createUniAPI('setStorage') // 设置存储
export const uniLogin = createUniAPI('login') // 登录
export const uniRequestPayment = createUniAPI('requestPayment') // 支付
// 检查登录状态,未登录则跳转
export const checkLogin = (message = '请登录') => {
const userStore = useUserStore()
if (!userStore.hasLogin) {
uni.navigateTo({ url: '/pages/login/index' }) // 跳登录页
uni.showToast({ title: message, icon: 'none' }) // 显示提示
throw new Error(message) // 抛出错误
}
}
在src目录下新建utils文件夹,src/utils/request.js
import { BASE_API_URL } from '@/env/index.js'
import { uniRequest } from '@/utils' // 基础请求方法
import { useUserStore } from '@/stores/user'
const store = useUserStore()
// 业务请求封装:自动加token、统一错误处理
export const apiRequest = async (options, config = {}) => {
let url = options.url
const header = options.header || {}
// 自动添加token到请求头
if (store.access_token) {
header.authorization = `Bearer ${store.access_token}`
}
// 处理URL:相对路径转绝对路径
url = url.startsWith('http') ? url : BASE_API_URL + url
try {
const response = await uniRequest({
...options,
header: {
'CLIENT-TOC': 'Y', // 客户端标识
'TENANT-ID': '10000888', // 租户ID
'Accept-Language': 'zh-CN', // 语言偏好
Cch: 'Y2Nodw==', // 自定义业务头
...header // 合并自定义头
},
url
})
// 统一处理响应数据
return handleResponse(response, config)
} catch (error) {
console.error('请求失败:', error)
return handleError(error, config)
}
}
// 处理成功响应:检查状态码和业务code
const handleResponse = (res, config) => {
const { statusCode, data } = res
// 显示业务错误提示
if (data.code != 0 && data.message && !config.noToast) {
uni.showToast({ title: data.message, icon: 'none', duration: 2500 })
}
// Token过期处理(401/424)
if ([401, 424].includes(statusCode)) {
handleTokenExpired()
throw res
}
// 其他HTTP错误处理(400+)
if (statusCode >= 400 && !config.noToast) {
handleHttpError(statusCode, data)
throw res
}
return res
}
// Token过期:退出登录并跳转
const handleTokenExpired = () => {
const store = useUserStore()
store.loginOut() // 清除用户状态
uni.showToast({ title: '请重新登录', icon: 'none' })
setTimeout(() => {
uni.navigateTo({ url: '/pages/login/login' }) // 跳登录页
}, 1000)
}
// HTTP错误处理:根据状态码显示对应提示
const handleHttpError = (statusCode, data) => {
const errorMessages = {
400: data.msg || '请求参数错误',
404: data.msg || '资源不存在',
500: data.msg || '服务器错误',
503: '网络异常,请稍后重试'
}
uni.showToast({
title: errorMessages[statusCode] || `服务器错误: ${statusCode}`,
icon: 'none'
})
}
// 网络请求失败处理
const handleError = (error, config) => {
if (!config.noToast) {
uni.showToast({ title: '网络请求失败,请检查网络', icon: 'none' })
}
return Promise.reject(error)
}
使用
import { request } from '@/utils/request'
export const getAreaTree = async (params) => {
return request({
url: '/admin/xxx/xxxx',
method: 'GET',
params
})
}
五、引入ui框架
5.1、uview组件库
介绍 | uview-plus - 全面兼容nvue/鸿蒙/uni-app-x的uni-app生态框架 - uni-app UI框架
5.1.1、安装插件



此时HBuilderx会弹框,选择项目点击确定


5.1.2、uView Plus配置
安装成功只是第一步,要让 uView Plus在项目中真正运行起来,还需要一些配置。
第一步:配置 easycom自动导入规则
这是最重要的一步,配置后你就可以直接在页面中使用组件,无需手动导入。
-
打开你项目根目录的
pages.json 文件。 -
在顶层添加以下
easycom节点:
// pages.json
{
"easycom": {
"autoscan": true, // 开启自动扫描
"custom": {
// uView Plus 的 easycom 规则
"^u--(.*)": "uni_modules/uview-plus/components/u-$1/u-$1.vue"
}
},
// ... 你原有的 pages、globalStyle 等配置
}
第二步:引入基础样式和图标样式
uView Plus的样式需要单独引入,否则组件会没有样式。
-
打开项目根目录的
uni.scss 文件。 -
如果文件不存在,就自己创建一个。
-
在文件中添加以下行:
// uni.scss
/* 引入uView Plus基础样式 */
@import 'uni_modules/uview-plus/index.scss';
/* 引入uView Plus图标样式 */
@import 'uni_modules/uview-plus/theme.scss';
第三步:在 main.js中安装插件 (可选但推荐)
虽然通过 easycom可以直接使用组件,但在 main.js中安装可以启用一些全局特性。
打开 main.js或 main.ts,添加以下代码:
// main.js 或 main.ts
import { createSSRApp } from 'vue'
import App from './App.vue'
import uviewPlus from 'uni_modules/uview-plus' // 导入uView Plus
export function createApp() {
const app = createSSRApp(App)
// 使用 uView Plus
app.use(uviewPlus)
return {
app
}
}
配置完成后,你无需在任何页面中 import组件,就可以直接在 <template>中使用所有 uView Plus的组件了。
<template>
<view class="container">
<!-- 直接使用 uView Plus 的按钮组件 -->
<u-button type="primary" text="这是一个uView按钮"></u-button>
<!-- 直接使用 uView Plus 的图标组件 -->
<u-icon name="home" size="28"></u-icon>
</view>
</template>
<script setup>
// 这里完全不需要引入组件!easycom 会自动处理。
</script>
最后一步:重启编译器!
非常重要: 完成以上配置后,请务必重新运行或重启你的 HBuilderX 项目(点击菜单栏的“运行”->“运行到浏览器或模拟器”),让配置生效。
六、可以愉快的写代码了
七、发布
第一步:编译
在 HBuilder X 中,菜单栏点击 【发行】-> 【小程序-微信】,然后输入你的小程序 AppID,HBuilder X 就会自动完成编译,并自动打开微信开发者工具。

第二步:点击“上传”按钮
-
编译完成后,项目会自动在 微信开发者工具 中打开。
-
点击顶部工具栏上的 【上传】 按钮。
-
这会要求你输入一个版本号和项目备注,然后代码就会被上传到微信的服务器,变成一个 “开发版本”。
第三步:提交审核和发布
-
登录 微信公众平台。
-
进入 【管理】-> 【版本管理】。
-
在 “开发版本” 栏中,你会看到你刚刚上传的代码版本。点击右侧的 【提交审核】。
-
按照提示填写相关信息,等待微信官方审核(通常需要1-7天,如截图所说,第一次较慢)。
-
审核通过后,你需要手动在微信公众平台的 “审核版本” 中,点击 【发布】,你的小程序才会正式上线给所有用户使用。
总结
-
编译:用 HBuilder X 把 uni-app 代码转换成小程序代码。
-
上传:在微信开发者工具中点击“上传”,将代码传到微信后台,形成“开发版本”。
-
提交审核:登录微信公众平台,将“开发版本”提交给微信官方审核。
-
发布:审核通过后,手动操作发布,小程序正式上线。
八、配置服务器域名白名单
入口:微信公众平台(这里必须是企业级)>开发管理>开发设置

注意:所有相关请求都需要配置进去,包括使用的第三方接口如百度、阿里,否则正式服无法访问
刚进企业派发小程序任务,如何进行开发?
- 先用git拉下项目
- 叫公司在微信公众平台把你的微信加入管理员
- 重新扫码微信开发者工具
- 如appId没有自动匹配就手动传入
更多推荐



所有评论(0)