这一部分需要结合视频观看,blog 不太容易去介绍😶🌫️😶🌫️😶🌫️
紧接前文,搭配有助于快速,巩固/学习!话不多说开始!
经过前面几篇的学习,好简单,最起码对于做过前端Vue 开发,小程序前后端 so so easy!
哦对了,顺便推荐一下之前的VUE学习blog,此篇有很多知识概念何Vue高度类似;
小程序 NPM
小程序已支持使用 npm 安装第三方包,开发者可以借助成熟的社区库快速实现功能,避免重复造轮子:
但受限于自身的运行环境,对 npm 包的使用存在明确限制:
小程序是运行在微信环境,并不是,浏览器环境;
不支持依赖 Node.js 内置库的包:
-
例如依赖
fs、path、http等 Node.js 内置模块的包, -
小程序的沙箱环境无法提供这些模块的实现,因此无法运行
不支持依赖 C++ 插件的包: 包含原生 C++ 插件包 如:部分加密、图像处理库,需要原生环境支持;
不支持依赖浏览器内置对象的包: 例如:依赖 window、document、navigator 等浏览器专属对象的包;
Vant Weapp
Vant Weapp🔗 是有赞前端团队开源的小程序 UI 组件库,
提供丰富的移动端组件:按钮、表单、弹窗 等...,可大幅提升小程序开发效率,采用 MIT 开源协议;

安装 Vant 组件库
尽量参考官方,随着时间和版本,问题不同环境存在差异!!!
步骤一 通过 npm 安装: 建议指定版本为@1.3.3
sh
# 如果项目第一次使用npm 还需要进行构建 package.json
npm init -y
# 通过 npm 安装
npm i @vant/weapp@1.3.3 -S --production
yarn add @vant/weapp --production # 通过 yarn 安装
npm i vant-weapp -S --production # 安装 0.x 版本

步骤二:修改app.json
将 app.json 中的 "style": "v2" 去除,
小程序的 新版基础组件 强行加上了许多样式,难以覆盖,不关闭将造成部分组件样式混乱;
步骤三:构建 npm 包: 微信开发者工具 工具 -> 构建 npm 构建完成后,即可引入组件;
旧版本: 还需要在项目设置中开启:使用npm 模块 ,新版本已经默认集成了配置;

引入|使用 Vant
安装完成后,通过 app.json全局引用 的 usingComponents 节点引入组件,即可在页面中直接使用:
js
{
"usingComponents": {
"van-button": "@vant/weapp/button/index"
}
}

全局主题样式
Vant Weapp 全局主题定制 CSS 变量方式
Vant Weapp 通过 CSS 变量 自定义属性 实现全局主题定制,
开发者只需在 app.wxss 中重写这些变量,即可统一所有组件的样式风格;
关于使用 CSS 自定义属性变量🔗🔗 复杂的网站都会有大量的 CSS 代码,通常也会有许多重复的值;
- 同样一个颜色值可能在成千上百个地方被使用到,如果这个值发生了变化,
- 需要全局搜索并且一个一个替换
很麻烦哎~,自定义属性在某个地方存储一个值,其他许多地方引用它;
Demo 案例: 以 butten 如果程序需要,定制按钮的颜色可以在,全局:app.wxss 统一配置;
在 page 选择器下定义 CSS 变量 :所有在 page 下定义的变量会全局生效,覆盖 Vant 的默认值;
css
/* app.wxss */
page {
/* 定制警告按钮的背景颜色 */
--button-danger-background-color: #c00073;
/* 定制警告按钮的边框颜色 */
--button-danger-border-color: #D60000;
}

Vant 组件内部大量使用 CSS 变量定义样式,开发者通过覆盖这些变量,
就能在不修改组件源码的情况下,实现全局主题风格的统一;
😶🌫️😶🌫️😶🌫️为什么是Page?为什么是这些配置??
在小程序中,所有页面的内容都被包裹在一个 <page> 标签内,这是小程序框架自动生成的 根容器;
在 page 选择器下定义的 CSS 变量,会被所有子元素 Vant组件继承,从而实现 全局生效;
为什么是 --button-danger-background-color 这个属性值???
详情可以参考: vant-weapp/packages/common/style/var.less GitHub
这个变量名是 Vant Weapp 组件库 内部预定义的 CSS 变量,遵循了清晰的语义化命名规则;

API Promise
本篇涉及文档blog:前后端交互的弯弯绕绕_前后端怎么相互调用的-CSDN博客
小程序原生的异步 API(如 wx.request 网络请求)默认采用 回调函数 的方式实现,例如:
js
wx.request({
method: '',
url: '',
data: {},
success: () => { /* 请求成功回调 */ },
fail: () => { /* 请求失败回调 */ },
complete: () => { /* 请求完成回调 */ }
})
多层嵌套会导致 回调地狱 Callback Hell ,代码层级深、可读性差;
错误处理和流程控制繁琐,代码维护成本高;
什么是 API Promise 化:
API Promise 化是指:通过工具或配置,将小程序官方提供的、
基于回调函数的异步 API,升级改造为基于 Promise 的异步 API。
我们可以使用 async/await 语法来编写异步代码,告别回调地狱,大幅提升代码可读性可维护性;
NPM 实现 API Promise 化:
安装依赖: 在项目根目录执行 npm 命令,安装指定版本的包:别忘记,小程序工具-构建npm
sh
npm install --save miniprogram-api-promise@1.0.4
在小程序入口文件 app.js中配置:
只需在 app.js 中调用一次 promisifyAll() 方法,即可完成所有异步 API 的 Promise 化:
js
// 1. 导入 promisifyAll 方法
import { promisifyAll } from 'miniprogram-api-promise'
// 2. 定义挂载对象,将 Promise 化后的 API 挂载到 wx.p 上
const wxp = wx.p = {}
// 3. 执行 Promise 化,将 wx 上的所有异步 API 转换为 Promise 版本
promisifyAll(wx, wxp)
// app.js
App({ /** 小程序配置 */ })
配置完成后,所有小程序原生异步 API 都会在 wx.p 对象上提供对应的 Promise 版本
调用 Promise 化后的异步 API
xml
<van-button type="danger" bindtap="getInfo">vant按钮</van-button>
js
// 定义 async 函数,处理按钮点击事件
async getInfo() {
// 使用 await 等待 Promise 化的 API 完成
const { data: res } = await wx.p.request({
method: 'GET',
url: 'https://www.escook.cn/api/get',
data: { name: 'zs', age: 20 }
})
// 打印请求结果
console.log(res)
}

全局数据共享:
全局数据共享(状态管理)是为了解决 组件间数据共享 的问题,避免多层嵌套传递数据的繁琐;
核心目标解决 多个组件 / 页面共享同一份数据 ,并且,数据变化时,所有用到该数据地方能自动更新🆙
小程序Mobx 全局数据共享: 类似于 Vuex、Redux
-
把 MobX 看作一个 全局数据仓库(Store),里面存着所有组件都需要用的公共数据;
-
任何组件都可以
订阅这个仓库里数据,当仓库里的数据变了,所有订阅了的组件会 自动更新 -
同时,MobX 要求必须通过
指定方式 Action修改仓库里的数据,保证数据变化可追踪、可调试;

MobX 全局数据共享
小程序中使用 MobX 实现全局数据共享,依赖两个 npm 包:
| 包名 | 作用 |
|---|---|
mobx-miniprogram |
用于创建 Store 实例对象,封装全局共享的数据和方法 |
mobx-miniprogram-bindings |
用于将 Store 中的数据和方法,绑定到页面或组件 中使用 |
sh
npm install --save mobx-miniprogram@4.13.2 mobx-miniprogram-bindings@1.2.1
⚠️ 注意: 在小程序开发者工具中,点击「工具」→「构建 npm」,重新生成构建后的 npm 包;
集中管理:所有共享数据和修改逻辑都集中在 Store 中,便于维护
简化通信:彻底告别了组件间层层传递数据的繁琐,让代码更清晰
响应式更新:当 Store 中的数据发生变化时,所有绑定了该数据的页面和组件会自动更新视图。
创建 MobX Store 实例
在项目中新建 store/store.js 文件,编写如下代码:
Store 是全局数据的容器,我们需要创建一个 Store 实例来管理共享状态:
js
// 从 mobx-miniprogram 中导入 observable 和 action
import { observable, action } from 'mobx-miniprogram'
// 使用 observable 创建 Store 实例
export const store = observable({
// 1. 数据字段(需要共享的数据)
numA: 1,
numB: 2,
// 2. 计算属性(getter,基于现有数据计算新值)
get sum() { return this.numA + this.numB },
// 3. actions 方法(修改 Store 中数据的唯一方式,必须用 action 包装)
updateNum1: action(function (step) {
this.numA += step
}),
updateNum2: action(function (step) {
this.numB += step
})
})
将 Store 绑定到页面
在页面中,我们需要将 Store 的数据和方法绑定到当前页面实例,以便在页面中直接使用:
页面 .wxml 使用: 在页面的 WXML 中,可以直接使用绑定的数据:
xml
<view>{{numA}} + {{numB}} = {{sum}}</view>
<van-button type="primary" bindtap="btnHandler1" data-step="{{1}}">
numA + 1
</van-button>
<van-button type="danger" bindtap="btnHandler1" data-step="{{-1}}">
numA - 1
</van-button>
页面 .js 文件配置
js
// 从 mobx-miniprogram-bindings 中导入 createStoreBindings
import { createStoreBindings } from 'mobx-miniprogram-bindings'
// 导入我们创建的 Store 实例
import { store } from '../../store/store'
Page({
/*** 页面的初始数据 */
data: { },
/* 生命周期函数--监听页面加载 */
onLoad: function () {
// 创建 Store 绑定
this.storeBindings = createStoreBindings(this, {
// 指定要绑定的 Store
store,
// 指定要绑定的数据字段(会自动映射到页面的 data 中)
fields: ['numA', 'numB', 'sum'],
// 指定要绑定的 actions 方法(会自动映射到页面的 this 上)
actions: ['updateNum1']
})
},
/* 生命周期函数--监听页面卸载 */
onUnload: function () {
// 页面卸载时,销毁 Store 绑定,避免内存泄漏
this.storeBindings.destroyStoreBindings()
},
// 页面方法,调用绑定的 action
btnHandler1(e) {
this.updateNum1(e.target.dataset.step)
}
})

将 Store 绑定到组件
在自定义组件中,我们通过 storeBindingsBehavior 来实现 Store 的自动绑定
组件 .wxml 使用: 在组件的 WXML 中,使用方式与页面完全一致:
xml
<view>{{numA}} + {{numB}} = {{sum}}</view>
<van-button type="primary" bindtap="btnHandler2" data-step="{{1}}">
numB + 1
</van-button>
<van-button type="danger" bindtap="btnHandler2" data-step="{{-1}}">
numB - 1
</van-button>
组件 .js 文件配置
js
// 从 mobx-miniprogram-bindings 中导入 storeBindingsBehavior
import { storeBindingsBehavior } from 'mobx-miniprogram-bindings'
// 导入我们创建的 Store 实例
import { store } from '../../store/store'
Component({
// 在 behaviors 中引入 storeBindingsBehavior
behaviors: [storeBindingsBehavior],
// 配置 Store 绑定
storeBindings: {
// 指定要绑定的 Store
store,
// 指定要绑定的数据字段(三种绑定方式)
fields: {
// 方式1:箭头函数
numA: () => store.numA,
// 方式2:函数参数(参数为 Store 实例)
numB: (store) => store.numB,
// 方式3:字符串(直接指定 Store 中的字段名)
sum: 'sum'
},
// 指定要绑定的 actions 方法
actions: {
updateNum2: 'updateNum2'
}
},
/* 组件的方法列表 */
methods: {
btnHandler2(e) {
// 调用绑定的 action 方法
this.updateNum2(e.target.dataset.step)
}
}
})

小程序分包:
分包基础概念
分包是将一个 完整的小程序项目,
按照业务需求划分为不同的子包,在构建时打包成独立的分包,
用户在使用时 按需进行加载 ,而非一次性下载全部代码,分包好处:👇
-
优化首次启动速度 :小程序启动时只下载主包,大幅减少首次加载时间,提升用户体验
-
团队协作解耦:在多团队共同开发时,不同业务模块可独立分包,降低代码耦合度,便于协作维护;
项目构成对比:
-
分包前 所有页面和资源
TabBar页、普通页、图片、脚本、样式等被打包在一起,导致项目体积过大,严重影响首次启动速度;

-
分包后 :项目由 1 个主包 + 多个分包 组成:
分包:只包含和当前分包业务相关的页面与私有资源,按需下载;
主包 :仅包含项目的启动页面、TabBar 页面,以及所有分包都需要用到的
公共资源;

加载规则: -
小程序启动时,默认只下载 主包 并启动主包内的页面,因此 TabBar 页面必须放在主包中
-
当用户进入分包内的某个页面时,客户端才会下载对应的分包,下载完成后再展示页面;
-
非 TabBar 页面可按功能划分到不同分包,实现按需加载;
体积限制: 整个小程序 主包 + 所有分包 的总大小不得超过 16M;
单个分包或主包的大小不得超过 2M;
小程序使用分包
在 app.json 中通过 subpackages 节点声明分包结构,示例如下:
-
root:分包的根目录,如moduleA -
pages:当前分包下所有页面的相对路径, -
name:分包的别名可选,用于分包预下载等场景

小程序严格按照 subpackages 配置分包,subpackages 之外所有目录/文件,被打包到主包中:
TabBar 页面必须放在主包内,否则无法正常显示
主包可以有自己的页面,配置在最外层的 pages 字段中
分包之间不能互相嵌套,即一个分包的根目录不能是另一个分包的子目录;
引用原则:
-
分包之间 不能相互引用 对方的私有资源。
-
主包 无法引用 分包内的私有资源
如: 分包内的图片、脚本等 -
分包 可以引用 主包内的公共资源
如: 主包的公共脚本、样式、图片等

和普通页面一样,在app.json 中配置对应目录,系统会自动创建出对应的文件目录;
小程序独立分包
独立分包本质上也是分包,但它是一种特殊的分包,
可以 独立于主包和其他分包而单独运行, 用户无需下载主包即可直接打开独立分包内的页面;
| 类型 | 运行依赖 |
|---|---|
| 普通分包 | 必须依赖主包才能运行,用户进入分包页面前需先下载主包 |
| 独立分包 | 可在不下载主包的情况下独立运行,大幅提升页面启动速度 |
应用场景: 适用于 功能独立性较强 页面,如:活动页、推广页、工具页 配置独立分包,原因:
-
普通分包启动时需先下载主包,而独立分包可直接运行,显著提升启动速度。
-
一个小程序中可以配置多个独立分包
配置方法: 在 app.json 的 subpackages 节点中,通过添加 "independent": true 来声明独立分包:
js
{
"pages": [
"pages/home/home",
"pages/message/message",
"pages/contact/contact"
],
"subpackages":[
{
"root": "pkgA",
"pages": [
"pages/cat/cat",
"pages/dog/dog"
]
},
{
"root": "pkgB",
"name": "pack2",
"pages": [
"pages/apple/apple",
"pages/banana/banana"
],
"independent": true // 声明为独立分包
}
],
"tabBar": { /*...*/ },
"window": { /*...*/ },
}
⭐⭐引用原则 重要: 独立分包与主包、普通分包之间是 相互隔绝 的,资源引用有严格限制:
-
主包无法引用独立分包内的私有资源
-
独立分包之间不能相互引用私有资源
-
独立分包和普通分包之间不能相互引用私有资源
特别注意 :独立分包中 不能引用主包内的公共资源,需将依赖的资源打包到独立分包自身;
分包预下载:
分包预下载是指: 在进入小程序的某个页面时,由框架自动预下载可能需要的分包;
当用户后续进入这些分包页面时,无需再次下载,从而提升启动速度;
配置分包预下载:
在 app.json 中,通过 preloadRule 节点定义预下载规则:
js
{
"preloadRule": {
"pages/contact/contact": { // 触发预下载的页面路径
"network": "all", // 网络模式:all(不限网络)或 wifi(仅WiFi,默认值)
"packages": ["pkgA"] // 预下载的分包,通过 root 或 name 指定
}
}
}
-
network:控制预下载网络环境,可选值为all 不限网络或wifi 仅在 WiFi 下预下载,默认值 -
packages:指定进入触发页面后,需要预下载分包,可通过分包root\name字段来指定;
预下载限制: 同一个分包中的页面共享 共同的预下载大小限额 2M
-
预下载的分包总体积不得超过 2M,否则预下载会被框架拦截🧱🧱;
-
例如:若从主包的
contact页面预下载分包 A、B、C,则A+B+C的体积必须小于 2M;
相关文档
黑马---小程序简介_哔哩哔哩_bilibili 对应:Day5 天内容!
这一部分需要结合视频观看,blog 不太容易去介绍😶🌫️😶🌫️😶🌫️