微信小程序开发的总结
1.微信小程序仅支持https请求,在开发时,可以设置官方编辑器中的详情->勾选“不检验合法域名....”,使用http开发、测试
2.由于小程序每个页面的cookie=“SESSIONID”处于变化中,使用session时,在发送https请求在header中设定cookie的值,不过不建议这样,建议在采用在redis保存信息,key保存在stroge中,value保存在redis中。
3.小程序登录流程
3.1登录流程:
- 客户端(微信小程序)发起请求
request
-
weapp-session-client 包装
request
-
首次请求
- 调用
wx.login()
和wx.getUserInfo()
接口获得code
、rawData
和signature
-
requset
的头部带上code
、rawData
和signature
- 保存
code
供下次调用
- 调用
-
非首次请求
-
request
的头部带上保存的code
-
-
-
服务器收到请求
request
,中间件从头部提取code
、rawData
和signature
字段- 如果
code
为空,跳到第4
步 -
如果
code
不为空,且rawData
不为空,需要进行签名校验-
使用
code
,appid
、app_secret
请求微信接口获得session_key
和openid
- 如果接口失败,响应
ERR_SESSION_KEY_EXCHANGE_FAILED
- 如果接口失败,响应
- 使用签名算法通过
rawData
和session_key
计算签名signature2
-
对比
signature
和signature2
-
签名一致,解析
rawData
为wxUserInfo
- 把
openid
写入到wxUserInfo
- 把
(code, wxUserInfo)
缓存到 Redis - 把
wxUserInfo
存放在request.$wxUserInfo
里 - 跳到第
4
步
- 把
- 签名不一致,响应
ERR_UNTRUSTED_RAW_DATA
-
-
-
如果
code
不为空,但rawData
为空,从 Redis 根据code
查询缓存的用户信息- 找到用户信息,存放在
request.$wxUserInfo
字段里,跳到第4
步 - 没找到用户信息(可能是过期),响应
ERR_SESSION_EXPIRED
- 找到用户信息,存放在
- 如果
-
request
被业务处理,可以使用request.$wxUserInfo
来获取用户信息(request.$wxUserInfo
可能为空,业务需要自行处理)
3.2流程图总结
-
code
是微信用户的登录凭证,打开小程序登录的时候获取的只属于微信这个用户的登录凭证,需要注意的是,这个登录凭证只供微信小程序使用的。 -
session_key
是微信用户在小程序里面的登录态信息,相当于是微信给这个用户颁发的一个登录 session,官网地址- 他有一个过期时间
{"session_key":"...","expires_in":7200,"openid":"..."}
,需要定期使用wx.checkSession检测。
- 他有一个过期时间
-
openId
,用户的唯一标识 -
unioinId
,如果开发者拥有多个移动应用、网站应用、和公众帐号(包括小程序),可通过unionid
来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号(包括小程序),用户的unionid
是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,unionid
是相同的。 - 一般来说,
openId
就是微信用户的唯一标识,但是因为微信产品很多,所以会出现多个微信产品使用不同的openId
来标识用户,但是对于我们做业务接入的话,就买办法使用了,所以建议是统一使用unioinid
,因为一般来说,一般的业务都会有公众号,小程序联合使用的。 -
3rd_session
是一般是指我们自己公司的服务器的session
,一般来说,可以跟原来的业务的session
一起使用,不过这个session
的过期时间一定要比小程序的session_key
的过期时间要长,这样可以减少session
的多次重复创建,另外一般我们自己公司的服务器的session
管理都会使用类似 redis 之类的数据库进行管理的,这个大致了解一下,因为其他文章会提到。 - 为什么要用2个
session
(session_key
和3rd_session
),那是因为session_key
是微信的登录态,3rd_session
是我们业务系统的登录态,两边各有一个登录态,所以需要将2个登录态合并为一个session
,在这里面是合并为3rd_session
,并保存到我们业务系统上,然后每次需要使用的时候,小程序带上这个3rd_session
访问我们的业务系统,通过处理,可以返回我们需要 unioinid 和其他session
信息而不用每次都去获取一个新的session_key
(因为微信有限制code 的使用,要用 code 换 session_key),总的来说,就是使用3rd_session
来管理小程序的登录
4.import和include的区别:
import是引用模板文件
<!--item.wxml-->
<template name="item">
<text>{{text}}</text>
</template>
<!--引用item.wxml-->
<import src="item.wxml" />
<template is="item" data="{{text:'forbar}}" />
include是引用除模板以外的文件
<!--index.wxml-->
<include src="header.wxml" />
<view>body</view>
<include src="footer.wxml"/>
<!--header.wxml-->
<view>header</view>
<!--footer.wxml-->
<view>footer</view>
5.链接组件
wx.navigateTo:保留当前页面,即可以返回,触发当前页面的hide事件
wx.redirectTo:不保留当前页面,页面的左上角没有“返回键”,在跳转的时候,会触发当前页面的hide,unlock事件
wx.switchTab:跳到在app.json配置的导航页面,关闭其他所有非tabBar页面,并且路径中不可以带参数
wx.navigateTo和wx.redirectTo不能跳到tabbar页面
6.生命周期函数
onLoad:页面加载时,一个页面只触发一次
onShow:页面显示时,每打开一次触发一次
onReady:页面初次渲染完成时,一个页面只触发一次
onHide:页面隐藏时,当navigateTo和底部tab切换时触发
onUnload:页面卸载,redirectTo和navigateBack调用时触发
7.<web-view src="" /> 其中src和页面iframe必须在官网中 业务服务器 进行配置,才能访问,而且一个页面只能配置一个,自动全屏,遮挡其他的节点
8.input绑定bindchange属性,以获取input输入的值
<!--index.wxml-->
<input bindchange="bindChange"/>
<!--index.js-->
page({
data:{
inputContent:{}
},
bindChange:function(e){
inputContent[e.currentTarget.id] = e.detail.value
}
})
9.改变窗口的背景颜色
page{
background-color:red;
}
10.事件
10.1 分为两种:冒泡事件,触发子组件,会触发给父组件的事件
非冒泡事件:触发子组件,不会触发父组件的事件
10.2 绑定事件的格式
bind+事件名称 = 函数名 catch+事件名称 = 函数名
基础库1.5.0以后 可以:bind:事件名称 = 函数名 catch:事件名称 = 函数名
使用bind不会阻止冒泡事件 使用catch会阻止冒泡事件
10.3 事件的捕捉阶段
从基本库1.5.0开始,支持触摸事件的捕捉阶段,在冒泡事件的触发之前,并与冒泡事件的触发组件顺序相反
格式 capture-bind
和capture-catch
,后者将阻止捕捉阶段和阻止冒泡事件,例子如下:
<view id="outer" bind:touchstart="handleTap1" capture-catch:touchstart="handleTap2">
outer view
<view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">
inner view
</view>
</view>
这样的点击inner组件,只触发handleTap2函数
10.4 事件对象
触发事件,在函数中将接受事件对象,将其console.log打印如下
{
"type":"tap",//触发事件类型
"timeStamp":895,//触发事件的时间戳
"target": {//触发事件的组件的属性
"id": "tapTest",
"dataset": {//在组件中设定的属性
"hi":"WeChat"//data-hi="WeChat"
}
},
"currentTarget": {//当前事件的组件的一个属性
"id": "tapTest",
"dataset": {
"hi":"WeChat"
}
},
"detail": {//
"x":53,
"y":14
},
"touches":[{//触摸动作的属性
"identifier":0,
"pageX":53,
"pageY":14,
"clientX":53,
"clientY":14
}],
"changedTouches":[{//
"identifier":0,
"pageX":53,
"pageY":14,
"clientX":53,
"clientY":14
}]
}
11.模块的使用
<wxs src="" module="" />标签
module:命名规则:必须以字母,数字和下划线组成,并且不以数字开头
建议在同一个wxml文件中,使用唯一的module,否则后面的会覆盖前面。
// /pages/tools.wxs
var foo = "'hello world' from tools.wxs";
var bar = function (d) {
return d;
}
module.exports = {
FOO: foo,
bar: bar,
};
module.exports.msg = "some msg";
<!-- page/index/index.wxml -->
<wxs src="./../tools.wxs" module="tools" />
<view> {{tools.msg}} </view>
<view> {{tools.bar(tools.FOO)}} </view>