一、开发前的准备

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样式(如添加-webkit-前缀等),

解决不同平台下的样式兼容性问题。

​上传代码时自动压缩​

​推荐开启​

压缩JS/CSS代码,确保不超过微信2MB限制

​检查安全域名和TLS版本​

​可选​

检查API域名是否在微信后台配置,避免线上请求失败

​位置接口​

​按需开启​

如果您的小程序需要获取用户地理位置信息(例如地图、外卖、打车应用),则​​必须勾选此项​​。它会在小程序配置中声明requireLocation权限。

​uniPush2.0​

​按需开启​

如果您需要使用DCloud提供的、支持全端(App、小程序、Web)的统一推送服务,则需勾选并配置此项。

​开启云端一体安全网络​

​按需开启​

防止抓包、数据加密,适合金融等高安全场景

3.2 pages.json

pages.json是 uni-app 的全局配置文件。

页面路径​ - 有哪些页面,怎么访问。

全局样式​ - 导航栏颜色、标题文字等。

TabBar​ - 底部/顶部导航栏。

组件引入​ - 自动导入规则。

开发模式​ - 直达页面的启动方式。

1、核心配置项速查表

配置项

作用一句话说明

注意点

​​pages​​

定义所有页面路径,第一项为首页

增删页面必须修改此数组

​​globalStyle​​

设置所有页面的导航栏、背景色等​

会被页面单独样式覆盖

​​tabBar​​

​​配置底部/顶部选项卡导航​

最少2个,最多5个Tab

​​easycom​​

​​开启组件自动导入,无需import

开发效率神器

​​condition​​

开发期间模拟直达页面场景

开发环境生效

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)

位置限制

position: "top"仅微信小程序支持

个性化配置 - 中间凸起按钮

{
  "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" // 选中颜色
      }
    }
  }
}

🚨 重要提示:

  1. 仅当list有偶数个Tab时才生效

  2. 平台限制:仅支持 App(2.3.4+) 和 H5(3.0.0+)

  3. 无pagePath:需手动监听点击事件

  4. 交互实现

// 在需要监听的文件中
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"
      }
    ]
  }
}

使用方法:

  1. 配置condition后保存

  2. 微信开发者工具 → 编译模式 → 选择配置的模式

  3. 点击"编译"即可直达对应页面

完整示例:

{
  // 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、主要子配置项速查表

父配置项

子配置项

作用

​​pages​​

path

​​页面路径,例如 "pages/index/index"。​​

style

​​单独设置该页面的样式,会覆盖全局样式。​​

​​globalStyle​​

navigationBarTitleText

​​导航栏标题文字(如“首页”)。​​

navigationBarBackgroundColor

​​导航栏背景颜色(如"#007AFF")。​​

enablePullDownRefresh

​​是否开启全局下拉刷新。​​

onReachBottomDistance

页面上拉触底事件,触发时距页面底部距离,单位只支持px

backgroundColor

下拉显示出来的窗口的背景色

backgroundTextStyle

下拉 loading 的样式,仅支持 dark / light

​​tabBar​​

list

​​Tab 列表,​​至少2个,最多5个。​

list.pagePath

​​Tab对应页面路径,必须在 pages中已定义。​​

list.text

​​Tab上显示的文字(如“首页”)。​​

list.iconPath

​​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中,这行代码会被当做注释忽略掉。

#ifdef

​条件编译指令​

意思是 ​​"if defined"(如果定义了)​​。这是uni-app提供的特殊语法。

MP-WEIXIN

​平台标识​

特指​​微信小程序平台​​(Mini Program - Weixin)。

常用平台标识符

标识

平台

MP-WEIXIN

微信小程序

MP-ALIPAY

支付宝小程序

MP-BAIDU

百度小程序

H5

Web浏览器(H5)

APP-PLUS或 APP

App

MP-TOUTIAO

抖音/头条小程序

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自动导入规则

这是最重要的一步,配置后你就可以直接在页面中使用组件,无需手动导入。

  1. 打开你项目根目录的 ​pages.json​ 文件。

  2. 在顶层添加以下 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的样式需要单独引入,否则组件会没有样式。

  1. 打开项目根目录的 ​uni.scss​ 文件。

  2. 如果文件不存在,就自己创建一个。

  3. 在文件中添加以下行:

// 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. 登录 ​​微信公众平台​​。

  2. 进入 ​​【管理】-> 【版本管理】​​。

  3. 在 ​​“开发版本”​​ 栏中,你会看到你刚刚上传的代码版本。点击右侧的 ​​【提交审核】​​。

  4. 按照提示填写相关信息,等待微信官方审核(通常需要1-7天,如截图所说,第一次较慢)。

  5. ​审核通过后​​,你需要手动在微信公众平台的 ​​“审核版本”​​ 中,点击 ​​【发布】​​,你的小程序才会正式上线给所有用户使用。

总结

  1. ​编译​​:用 HBuilder X 把 uni-app 代码转换成小程序代码。

  2. ​上传​​:在微信开发者工具中点击“上传”,将代码传到微信后台,形成“开发版本”。

  3. ​提交审核​​:登录微信公众平台,将“开发版本”提交给微信官方审核。

  4. ​发布​​:审核通过后,手动操作发布,小程序正式上线。

八、配置服务器域名白名单

入口:微信公众平台(这里必须是企业级)>开发管理>开发设置

注意:所有相关请求都需要配置进去,包括使用的第三方接口如百度、阿里,否则正式服无法访问

刚进企业派发小程序任务,如何进行开发?
  • 先用git拉下项目
  • 叫公司在微信公众平台把你的微信加入管理员
  • 重新扫码微信开发者工具
  • 如appId没有自动匹配就手动传入
Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐