小程序相关
一、常用基础组件
Rich-text
作用: 解析html代码, 与v-html和innerHTML相似
<rich-text nodes="{{ str }}"></rich-text>
Picker
<!-- 普通选择器 -->
<picker mode="selector" range-key="name" range="{{ arr }}" bindchange="change1">
<button>选择职业</button>
</picker>
<!-- 多列选择器 -->
<picker mode="multiSelector" range="{{ brr }}" bindchange="change1">
<button>选择职业</button>
</picker>
<!-- region 地区选择器 -->
<picker mode="region" bindchange="change2">
<button>选择地区</button>
</picker>
二、分包
某些情况下,开发者需要将小程序划分成不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载。每个使用分包小程序必定含有一个主包。所谓的主包,即放置默认启动页面/TabBar 页面,以及一些所有分包都需用到公共资源/JS 脚本;而分包则是根据开发者的配置进行划分。
优势
1.在小程序启动时,默认会下载主包并启动主包内页面,当用户进入分包内某个页面时,客户端会把对应分包下载下来,下载完成后再进行展示。
2.单个分包/主包大小不能超过 2M,整个小程序所有分包大小不超过 20M,能够将工程大小扩充到20M
3.对小程序进行分包,可以优化小程序首次启动的下载时间,以及在多团队共同开发时可以更好的解耦协作。
分包结构里面:
//主包
//普通分包
//独立分包
不依赖于主包的,也就是说,第一次直接进入独立分包,那么不会先加载主包,就是第一次使用不了 主包的内容;
*各个包之间是可以进行正常跳转的;
*如果第一次进入小程序,进入的是主包中的页面,则只加载主包的内容,如果第一次 进入的是普通分包的页面,则需要先加载主包,在加载分包;
*当从一个分包/主包跳转到其他的分包的时候,再去加载其他的分包;
1.配置分包结构
app.json
"subPackages": [
{
"root": "pageA",
"pages": [
"cat/cat",
"dog/dog"
]
},
{
"root": "pageB",
"pages": [
"apple/apple"
]
}
]
2.独立分包
"subPackages": [
{
"root": "pageA",
"pages": [
"cat/cat",
"dog/dog"
]
},
{
"root": "pageB",
"pages": [
"apple/apple"
],
"independent": true // 独立分包
}
]
3.分包预下载
"preloadRule": {
"pages/shop/shop":{
"network": "all",
"packages": ["pageA","shuiguo"]
}
}
三、计算属性
computed计算属性
1.概述
computed是小程序自定义组件扩展 behavior,在小程序组件中,计算属性 computed 和监听器 watch 的实现。在 data 或者 properties 改变时,会重新计算 computed 字段并触发 watch 监听器。目前针对的是component,在页面使用需要引入其他的三方库;
2.安装
npm install --save miniprogram-computed
3.computed 基本用法
// 引入computed
const computedBehavior = require('miniprogram-computed').behavior
Page({
behaviors:[computedBehavior], // 注册
data:{
numA:1,
numB:2,
sum:0
},
// computed:{
// sum(data){
// return data.numA+data.numB;
// }
// },
watch:{
"numA,numB":function(a,b){
// console.log(a,b);
this.setData({
sum:a+b
})
}
},
change(){
this.setData({
numA:++this.data.numA,
numB:++this.data.numB
})
}
})
4.watch 基本用法
// pages/computed/computed.js
// 注册页面,2种注册方式,
// 1.使用Page构造器构造页面,
// 2.使用Component构造器构造页面
const computedBehavior = require("miniprogram-computed").behavior;
Component({
behaviors: [computedBehavior],
data: {
numA: 1,
numB: 2,
sum: 0,
},
attached() {
this.setData({
sum: this.data.numB + this.data.numA
})
},
// watch中可以直接使用this
watch: {
"numA,numB": function (a, b) {
// console.log(a,b)
this.setData({
sum: a + b
})
}
},
methods: {
onLoad(options) {
console.log(options)
},
changeNum() {
this.setData({
numA: ++this.data.numA,
numB: ++this.data.numB
})
},
onPullDownRefresh(){
console.log('下拉刷新')
}
}
})
5.购物车实现
wxml
<!-- 购物车列表 -->
<!--
@params
products 购物车商品 必须
bindsubmit 结算事件 可选
binddelete 删除事件 可选
-->
<view class="container">
<block wx:for="{{ products }}" wx:key="id">
<view class="itemlist">
<switch class="swicth" bindchange="_changeChecked" data-index="{{ index }}" checked="{{ item.checked }}" type="checkbox"></switch>
<!-- 图片 -->
<image class="image" src="{{ item.goodspic }}"></image>
<view class="info">
<view class="infoaction">
<view>{{ item.goodsname }}</view>
<view bindtap="_cartDelete" data-id="{{ item.id }}" data-index="{{ index }}">删除</view>
</view>
<view class="infolist">
<view>¥{{ item.price }}</view>
<view class="number">
<text class="text" bindtap="desc" data-index="{{ index }}" >-</text>
<text class="text">{{ item.num }}</text>
<text class="text" bindtap="asc" data-index="{{ index }}">+</text>
</view>
</view>
</view>
</view>
</block>
</view>
<view class="bottom">
<switch type="checkbox" bindchange="_changeAllChecked" checked="{{ allChecked }}" class="bottom-l">全选</switch>
<view class="bottom-r">
<view>合计:{{ totalPrice }}</view>
<view class="jiesuan" bindtap="formSubmit">结算({{ totalNum }})</view>
</view>
</view>
wxss
/* components/cart/cart.wxss */
.container .itemlist .image{
width: 80px;
height: 80px;
flex: 3;
}
.container .itemlist{
width: 100%;
height: 100px;
border: 1px solid #ccc;
display: flex;
justify-content: space-between;
align-items: center;
}
.container .itemlist .switch{
flex: 1;
}
.container .itemlist .info{
flex: 7;
margin-left: 20px;
display: flex;
flex-direction: column;
justify-content: space-between;
height: 80px;
}
.infolist{
display: flex;
justify-content: space-between;
}
.number .text{
margin-right: 10px;
}
.bottom{
width: 100%;
height: 45px;
background-color: #123456;
display: flex;
justify-content: space-between;
color: #fff;
align-items: center;
position: fixed;
left: 0;
bottom: 0;
}
.bottom-l,.bottom-r{
display: flex;
justify-content: space-between;
align-items: center;
}
.jiesuan{
margin-left: 20px;
}
.infoaction{
display: flex;
justify-content: space-between;
padding-right: 10px;
}
js
products:[
{
id:1,
goodsname:"小米手机",
goodspic:"/pages/cart/0.jpg",
num:1,
price:1000,
checked:true
},
{
id:2,
goodsname:"苹果手机",
goodspic:"/pages/cart/1.jpg",
num:2,
price:2000,
checked:true
}
]
四、获取用户信息
旧版本
<button open-type="getUserInfo" bindgetuserinfo="_getUserInfo">
获取用户信息
</button>
wx.getUserInfo()
1. 通过API获取用户信息
wxml
<view wx:if="{{ isLogin }}">
<view>昵称:{{ userInfo.nickName }}</view>
<image style="width: 50px;height: 50px;border-radius: 50%;" src="{{ userInfo.avatarUrl }}"></image>
</view>
<button wx:else bindtap="_getUserInfo" >获取用户信息</button>
js
// 新版本获取用户信息
_getUserInfo(){
if(!wx.getUserprofile){
wx.showModal({
title:"版本提示",
content: "您的微信客户端版本过低,请升级客户端版本"
})
return;
}
//获取用户信息
let that=this;
wx.getUserProfile({
desc:'显示信息',
success(res){
this.setData({
userInfo:res.userInfo,
isLogin:true
})
wx.setStorageSync('userInfo',res.userInfo)
}
})
}
五、获取手机号
(1)获取微信用户绑定的手机号,需先调用wx.login接口;
(2)需要用户主动触发才能发起获取手机号接口,该功能不由 API 来调用,需用 button 组件的点击来触发
(3)目前该接口针对非个人开发者,且完成了认证的小程序开放(不包含海外主体)
使用方法:
需要将button组件设置 open-type="getPhoneNumber",当用户点击并同意后,可以通过 bindgetphonenumber 事件回调获取到微信服务器返回的加密数据, 然后在第三方服务端结合 session_key 以及 app_id 进行解密获取手机号。
测试号地址:https://developers.weixin.qq.com/sandbox
代码案例:
1. 旧版本
wxml
<button open-type="getPhoneNumber" bindgetphonenumber="_getPhoneNumber">
获取手机号
</button>
js
// 获取用户手机号
_getPhoneNumber(e){
wx.checkSession({
success:(res)=>{
wx:request({
url:'http://localhost:3000/v1/getPhoneNumber',
data:{
encrypteData,
iv
},
success(res){
console.log('真实的手机号',res)
},
})
},
fail(){
wx.login({
timeout:60000,
success(result){
let {iv,encryptedData}=e.detail;
wx.request({ url:'http://localhost:3000/v1/getPhoneNumber',
data:{
encryptedData,
iv,
code:result.code
},
success(res){
console.log('真实手机号',res)
}
})
}
})
}
})
}
服务端js接口
// console.log(req.query)
var WXBizDataCrypt = require('./WXBizDataCrypt')
// 解密
app.get('/v1/getPhoneNumber', async function(req, res) {
var {
encryptedData,
iv,
code = null
} = req.query;
// code == null ,没传。证明 原来的code是有效的,那么后端使用原来的sessionkey进行解密即可
// 反之,需要重新获取sessionkey,并且进行缓存
var appId = 'wx032683dda4359e31';
var secret = "b684d0bd8bca78eca7a398c209e4827d";
// https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
if(code == null){
// 将原来的sessionkey从session获取
var sessionKey = "session中的数据"
}else{
var result = await axios({
url: "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId + "&secret=" + secret +
"&js_code=" + code + "&grant_type=authorization_code",
method: "get"
})
var sessionKey = result.data.session_key;
// 将sessionKey存入session
}
var pc = new WXBizDataCrypt(appId, sessionKey)
var data = pc.decryptData(encryptedData, iv)
res.send({value:data})
});
新的版本
wxml
<!-- 2.获取手机号 新版本 -->
<button open-type="getPhoneNumber" bindgetphonenumber="_login">登录</button>
js
// 2.新版本获取用户手机号
_login(e){
// console.log(e)
var code = e.detail.code;
wx.request({
url: 'http://localhost:3000/v1/phone',
method:"post",
data:{code},
success(res){
console.log(res,'获取手机号')
}
})
},
服务端js接口
// 新版本
app.post("/v1/phone", async (req, res) => {
let {
code
} = req.body; // 获取传递的参数
var appId = 'wx032683dda4359e31';
var secret = "b684d0bd8bca78eca7a398c209e4827d";
// 获取接口凭证 get
// https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
var tokenres = await axios({
url: "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId +
"&secret=" + secret,
method: "get"
})
var token = tokenres.data.access_token;
// 获取手机号 post
// https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=ACCESS_TOKEN
var ress = await axios({
url: "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + token,
method: "post",
data: {
code
}
})
// console.log(res)
res.send({
value: ress.data.phone_info
})
})
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏