目前,小程序中已经支持使用p安装第三方包,从而来提高小程序的开发效率。但是,在小程序中使用npm包有如下3个限制:
虽然npm上的包有千千万万,当是可以为小程序使用的却不多
Vant Weapp是有赞前端团队开源的一套小程序UI组件库,助力开发者快速搭建小程序应用。它所使用的是MT开源许可协议,对商业使用比较友好。
官方参考文档如下:介绍 - Vant Weapp (youzan.github.io)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nJZvVTgT-1658322842026)(image/1、Vant Weapp.png)]](https://1000bd.com/contentImg/2022/07/27/124612258.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8IAuK9pE-1658322842027)(image/2、外部终端打开.png)]](https://1000bd.com/contentImg/2022/07/27/124612509.png)
npm init -y
初始化成功会在项目的根目录中生成一个package.json文件
npm i @vant/weapp@1.3.3 -S --production
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OiYaB2zk-1658322842027)(image/3、构建npm.png)]](https://1000bd.com/contentImg/2022/07/27/124612744.png)
目前开发者工具是没有使用npm模块选项了,构建npm包之后直接使用
将 app.json 中的 "style": "v2" 去除,小程序的新版基础组件强行加上了许多样式,难以覆盖,不关闭将造成部分组件样式混乱。
安装完Vant组件库之后,可以在app.json的usingComponents节点中引入需要的组件,即可在wxml中直接使用组件。示例代码如下:
"usingComponents": {
"van-button": "@vant/weapp/button/index"
}
在Vant Weapp官网对应的组件库中可以看到具体的引入信息
引入组件之后就可以在全局访问了
<van-button type="default">默认按钮van-button>
<van-button type="primary">主要按钮van-button>
<van-button type="info">信息按钮van-button>
<van-button type="warning">警告按钮van-button>
<van-button type="danger">危险按钮van-button>
Vant Weapp使用css变量来实现定制主题,基本用法参考:使用 CSS 自定义属性(变量) - CSS(层叠样式表) | MDN (mozilla.org)
element声明是有作用域的
element {
--main-bg-color: brown;
}
使用一个局部变量时用 var() 函数包裹以表示一个合法的属性值:
element {
background-color: var(--main-bg-color);
}
在小程序中page就是项目的根节点
page{
/*定制警告按钮的背景颜色和边框颜色*/
--button-danger-backgrount-color:#C00000;
--button-danger-border-color:#C60000;
}
关于定制变量的名称可以查看官方给出的进行修改:vant-weapp/var.less at dev · youzan/vant-weapp (github.com)
默认情况下,小程序官方提供的异步API都是基于回调函数实现的
缺点:容易造成回调地狱的问题,代码可读性、维护性差
API Promise化,指的是通过
额外的配置,将官方提供的、基于回调函数的异步API,升级改造为基于Promise的异步APl,从而提高代码的可读性、维护性,避免回调地狱的问题。
在小程序中,实现API Promise化主要依赖于miniprogram-api-promise这个第三方的npm包,安装和使用如下
npm install --save miniprogram-api-promise@1.0.4
每安装一个包都要进行构建
构建之前先将miniprogram_npm文件夹删除再构建
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vqSCNm6d-1658322842028)(image/4、miniprogram-api-promise@1.0.4.png)]](https://1000bd.com/contentImg/2022/07/27/124612948.png)
在小程序入口文件中(app.js)只需要调用一次promisifyAll()方法,即可实现异步API的promise化
// app.js
// 导入miniprogram-api-promise
import {promisifyAll} from 'miniprogram-api-promise'
// 定义成员
const wxp = wx.p = {}
// 调用promisifyAll方法实现promise化【wx被promise化后会挂载到wxp对象】
// 后面就可以使用wx.p来调用promise化后的API了
promisifyAll(wx,wxp)
按钮调用
<van-button type="primary" bindtap="getInfo">主要按钮van-button>
在对应页面.js文件中定义方法
async getInfo(){
const {data:res} = await wx.p.request({
url:'https://applet-base-api-t.itheima.net/api/get',
method:'get',
data:{
naem:'zs',
age:20
}
})
console.log(res)
}
全局数据共享(又叫做:状态管理)是为了解决组件之间数据共享的问题。
开发中常用的全局数据共享方案有:Vuex、Redux、MobX等。
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ytLi7pV4-1658322842028)(image/5、全局数据共享.png)]](https://1000bd.com/contentImg/2022/07/27/124613219.png)
在小程序中,可以使用mobx-miniprogram配合mobx-miniprogram-bindings实现全局数据共享
Store实例对象Store中的共享数据或方法,绑定到组件或页面中使用在项目中允许如下命令,安装Mobx相关的包
npm install --save mobx-miniprogram@4.13.2 mobx-miniprogram-bindings@1.2.1
记住删除miniprogram_npm目录后再构建npm
在项目的根目录中创建一个store的文件夹存放store.js文件
// 在这个js文件中,专门来创建Store的实例对象
import {observable,action} from 'mobx-miniprogram'
// 导出供外界使用
export const store = observable({
// 声明共享数据
NumA:1,
NumB:2,
// 计算属性的值,get只读属性不允许修改
get sum(){
return this.NumA + this.NumB
},
// 我们不可以在外界直接修改共享的数据,必须通过调用方法的方式进行修改
// actions方法,用来修改store中的数据
updateNum1:action(function(step){
this.NumA += step
}),
updateNum2:action(function(step){
this.NumB += step
})
})
// pages/message/message.js
// 导入指定的方法
import {createStoreBindings} from 'mobx-miniprogram-bindings'
import {store} from '../../store/store'
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 点击按钮调用+1或-1
*/
btnHandler1(e){
console.log(e)
this.updateNum1(e.target.dataset.step)
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
// 将需要的属性字段和方法绑定到当前页面的yhis
this.storeBindings=createStoreBindings(this,{
// 数据源
store,
// 需要绑定的数据和计算值绑定到页面
fields:['NumA','NumB','sum'],
// 需要绑定的方法
actions:['updateNum1','updateNum2']
})
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
this.storeBindings.destroyStoreBindings()
}
})
绑定之后就可以在页面中进行调用了
<text>numA的值:{{NumA}}text>
<view>numB的值:{{NumB}}view>
<view>{{NumA}} + {{NumB}} = {{sum}}view>
<view>view>
<van-button type="primary" bindtap="btnHandler1" data-step="{{1}}">NumA+1van-button>
<van-button type="danger" bindtap="btnHandler1" data-step="{{-1}}">NumA-1van-button>
numbers组件"usingComponents": {
"my-numbers": "./components/numbers/numbers"
}
<my-numbers>my-numbers>
// components/numbers/numbers.js
// 按需导入
import {storeBindingsBehavior} from 'mobx-miniprogram-bindings'
// 导入实例
import {store} from '../../store/store'
Component({
// 实现自动绑定
behaviors:[storeBindingsBehavior],
// 绑定关系
storeBindings:{
// 数据源
store,
fields:{
// 映射的字段:store里的字段被映射
NumA:'NumA',
NumB:'NumB',
sum:'sum'
},
actions:{
updateNum2:'updateNum2'
}
}
})
<text>numA的值:{{NumA}}text>
<view>numB的值:{{NumB}}view>
<view>{{NumA}} + {{NumB}} = {{sum}}view>
<view>view>
<van-button type="primary" bindtap="btnHandler2" data-step="{{1}}">numB+1van-button>
<van-button type="danger" bindtap="btnHandler2" data-step="{{-1}}">NumB-1van-button>
在组件的js文件中的methods节点创建上面的方法
/**
* 组件的方法列表
*/
methods: {
btnHandler2(e){
// 调用映射过来的updateNum2方法
this.updateNum2(e.target.dataset.step)
}
}
效果
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6PTGxiG3-1658322842029)(image/6、案例效果‘.png)]](https://1000bd.com/contentImg/2022/07/27/124613423.png)
分包指的是把一个
完整的小程序项目,安装需求划分为不同的子包,在构建时打包成不同的分包,用户在实用时按需进行加载
好处:
分包前,小程序项目中所有的页面和资源都被打包到了一起,导致整个项目体积过大,影响小程序首次启动的下载时间。
分包后,小程序项目由1个主包+多个分包组成
启动页面或TabBar页面,以及所有分包所需要用到的一些公共资源![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lbi9tAcs-1658322842029)(image/7、分包.png)]](https://1000bd.com/contentImg/2022/07/27/124613661.png)
在小程序启动时,默认回下载主包并启动主包页面
tabBar页面需要放到主包中
当用户进入分包内某个页面时,客户端回把对应的分包进行下载,下载后再进行展示
非tabbar页面可以按照功能的不同,划分为不同的分包之后,进行按需下载
在项目的app.json文件中通过
subPackages节点进行添加分包的路径,与pages节点同级关系
{
"pages":[
"pages/index/index",
"pages/message/message",
"pages/contact/contact"
],
"subPackages": [
{
"root": "pkgA", // 存放分包的根目录
"name": "p1", // 给分包起别名
"pages": [ // 当前分包下的所有页面的相对路径
"pages/cat/cat",
"pages/dog/dog"
]
},
{
"root": "pkgB",
"name": "p2",
"pages": [
"pages/apple/apple",
"pages/dog2/dog2"
]
}
]
}
输入路径之后保存开发者工具就会自动的生成分包的文件信息
在小程序详情的基本信息页面即可看到
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AvsOj5Y1-1658322842030)(image/8、体积.png)]](https://1000bd.com/contentImg/2022/07/27/124613897.png)
subpackages的配置进行分包,subpackages之外的目录将被打包到主包中无法引用分包内的私有资源不能相互引用私有资源可以引用主包内的公共资源独立分包
本质上也是分包,只不过它比较特殊,可以独立于主包和其他分包而独立运行
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5n3WeiPz-1658322842031)(image/9、独立分包.png)]](https://1000bd.com/contentImg/2022/07/27/124614217.png)
是否依赖于主包才能运行
开发者可以按需,将某些具有一定功能独立性的页面配置到独立分包中:
注意:一个小程序中可以有多个独立分包
在app.json文件中定义,于普通分包的区别就是多了一个independent属性来绝定为独立分包
"subPackages": [
{
"root": "pkgB",
"name": "p2",
"pages": [
"pages/apple/apple",
"pages/dog2/dog2"
],
"independent": true
}
]
}
独立分包和普通分包以及主包之间是相互隔离的,不能相互引用彼此的资源
无法引用独立分包内的私有资源不能相互引用私有资源分包预下载指的是:在进入小程序的某个页面时,
由框架自动预下载可能需要用到的分包,从而提示进入后续分包页面时的启动速度
预下载分包的行为,会在进入指定的页面时触发
在app.json中,使用preloadRule节点定义分包的预下载规则,代码如下
// 分包预下载的规则节点
"preloadRule": {
// 指定进入指定页面进行预下载路径
"pages/contact/contact": {
// 表示在指定的网络模式下进行预下载【all不限网络、wifi为默认】
"network": "all",
// 表示进入页面后,预下载哪一个分包【通过分包的root或name都可以进行指定】
"packages": ["pkgA"]
}
}
同一个分包中的页面享有
共同的预下载大小限额2M
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TBHh1IyO-1658322842031)(image/10、分包预下载限制.png)]](https://1000bd.com/contentImg/2022/07/27/124614577.png)
用到的知识点:
自定义tabBar分为3答步骤,分别是:
app.json 中的 tabBar 项指定 custom 字段,同时其余 tabBar 相关配置也补充完整。usingComponents 项,也可以在 app.json 全局开启。对应list数组必须要保留,不然可能底版本的不能兼容
"tabBar": {
"custom": true,
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "/images/tabs/home.png",
"selectedIconPath": "/images/tabs/home-active.png"
},
{
"pagePath": "pages/message/message",
"text": "消息",
"iconPath": "/images/tabs/message.png",
"selectedIconPath": "/images/tabs/message-active.png"
},
{
"pagePath": "pages/contact/contact",
"text": "我的",
"iconPath": "/images/tabs/contact.png",
"selectedIconPath": "/images/tabs/contact-active.png"
}
]
}
在项目的根目录中创建custom-tab-bar文件夹,命名必须是这一个不能改,并且在文件里面创建一个index组件名称也是不能改的
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T5dbPHap-1658322842032)(image/11、custom-tab-bar.png)]](https://1000bd.com/contentImg/2022/07/27/124614762.png)
当index组件创建完成后我们原有的tabBar中的list数组就会被该index.wxml页面结构所覆盖
推荐使用want weapp中的tabbar组件
需要使用相关的组件就需要引入对应的组件信息到项目
<van-tabbar active="{{ active }}" bind:change="onChange">
<van-tabbar-item wx:for="{{list}}" wx:key="index" info="{{item.info ? item.info:''}}">
<image
slot="icon"
src="{{ item.iconPath }}"
mode="aspectFit"
style="width: 25px; height: 25px;"
/>
<image
slot="icon-active"
src="{{ item.selectedIconPath }}"
mode="aspectFit"
style="width: 25px; height: 25px;"
/>
{{item.text}}
van-tabbar-item>
van-tabbar>
index.js中的tabBar数据【是组件.js文件】
/**
* 组件的初始数据
*/
data: {
active: 0,
list: [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "/images/tabs/home.png",
"selectedIconPath": "/images/tabs/home-active.png"
},
{
"pagePath": "pages/message/message",
"text": "消息",
"iconPath": "/images/tabs/message.png",
"selectedIconPath": "/images/tabs/message-active.png",
info:0
},
{
"pagePath": "pages/contact/contact",
"text": "我的",
"iconPath": "/images/tabs/contact.png",
"selectedIconPath": "/images/tabs/contact-active.png"
}
]
}
在info='0'属性可以指定生成的徽标数,但是不是每一个tabbar都会用到,可以在定义的data数据源中的tabbar需要的选项后面添加info:0字段来完成指定的选项添加
在没有解决之前图片的底部是由一个margin-bottom样式撑着导致放大后会看到徽标溢出
在自定义组件中使用 Vant Weapp 组件时,需开启styleIsolation: 'shared'选项【在组件.js文件中】
// custom-tab-bar/index.js
Component({
options:{
// 启用覆盖样式
styleIsolation:'shared'
}
})
覆盖的样式如下
/* custom-tab-bar/index.wxss */
.van-tabbar-item {
--tabbar-item-margin-bottom:0
}
// custom-tab-bar/index.js
import {selectedIconPath} from 'mobx-miniprogram-bindings'
import {store} from '../store/store'
Component({
behaviors:[selectedIconPath],
storeBindings:{
store,
fields:{
sum:'sum'
},
actions:{}
},
/**
* 数据监听器
*/
observers:{
'sum':function(str){
// 修改tabBar中的消息数据
this.setData({
'list[1].info':str
})
}
}
})
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9op2xqdY-1658322842033)(image/12、徽章效果.png)]](https://1000bd.com/contentImg/2022/07/27/124614944.png)
在监听tabBar栏上进行切换事件跳转页面
onChange(event) {
this.setData({ active: event.detail });
// 获取到地址进行跳转
wx.switchTab({
url: this.data.list[event.detail].pagePath,
})
}
原因:当点击其他的tabbar栏的时候被选中的标识不一定会出现在点击的那个tab栏上
将切换的索引active放到公共的组件store中存储
同时也要将index.wxml页面所使用的active进行移除
在store.js公共文件中声明一个方法专门修改索引的
updateActiveTabBarIndex:action(function(index){
this.activeTabBarIndex = index
})
在index.js文件中映射store中的新添加字段和修改方法
storeBindings:{
store,
fields:{
sum:'sum',
active:'activeTabBarIndex' // 映射的索引
},
actions:{
updateActive:'updateActiveTabBarIndex' // 修改索引的方法
}
}
在页面被切换的时候调用修改索引方法
onChange(event) {
this.setData({ active: event.detail });
// 修改切换的索引
this.updateActive(event.detail)
// 获取到地址进行跳转
wx.switchTab({
url: this.data.list[event.detail].pagePath,
})
}
在页面的标签中添加action属性
<van-tabbar active="{{active}}" bind:change="onChange"></<van-tabbar>
修改tabBar选中项的文本颜色
在标签上通过active-color="#13A7A0"属性进行修改
<van-tabbar active="{{active}}" bind:change="onChange" active-color="#13A7A0"/>
可以参考官方文档手册:自定义 tabBar | 微信开放文档 (qq.com)