小程序相关

一、常用基础组件

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
	})
})
posted @   又又儿  阅读(61)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏
点击右上角即可分享
微信分享提示