小程序的按需登录的实现代码及思想
目录
小程序的按需登录的实现代码及思想
微信小程序的用户登录发生了改变,以前是进入小程序后就让用户强制登录再进行后续操作,但是现在不同了,要求用户在需要登录的页面才进行登录
比如:在首页展示商品时,没有必要知道用户的信息,就不需要登录,点击商品进入到商品详情页的时候,也不需要用户登录,当用户点击购买商品时才让用户登录
这种场景怎么实现呢?
我的做法(先说思想)
因为不同的页面需要登录的情况不同, 那么我们就在小程序的 自定义组件中 自定义一个登录的组件 在pages的页面中,哪个页面需要登录,就在哪个页面中引入这个组件 就可以实现按需登录
下面再说一说 这个登录组件的思想
登录的组件要考虑用户 有没有 授权 如果授权过,则把登录组件隐藏,如果没有授权过,则显示登录的组件 ,要求用户通过button按钮来进行 登录授权
用户成功授权后,利用登录组件的 triggerEvent 来通知 父页面去加载初始数据 (注意,此时父组件的onload已经加载过了,没用了,只能通过子组件的triggerEvent来初始化数据)
有的登录还需要 用户 token 如下图
上一下代码:
login组件的代码
// components/authorize/auth.js
import { Auth } from "../../model/auth.js";
let auth = new Auth();
let app = getApp();
Component({
/**
* 组件的属性列表
*/
properties: {
isHidden:{
type:Number,
value:1 //1表示隐藏 0表示显示
},
isAutoLoad:{
type:Number,
value:1 //1表示自动登录, 0表示在没有授权的的情况下也不会自动登录
}
},
/**
- 组件的初始数据
*/
data: {
},
//在组件完全初始化完毕、进入页面节点树后, attached 生命周期被触发。此时, this.data 已被初始化为 组件的当前值。这个生命周期很有用,绝大多数初始化工作可以在这个时机进行。
attached:function(){
//组件加载完成后,要调用自动登录的方法
this.setLoadStatus();
},
/**
- 组件的方法列表
*/
methods: {
setLoadStatus:function(){
let _this = this;
wx.getSetting({
success:function(res){
if (!res.authSetting['scope.userInfo']){
//如果用户没有授权过,
if(_this.data.isAutoLoad == 0) return //如果设置的 isAutoLoad 为 0 则不会自动登录
if(_this.data.isAutoLoad == 1){
//显示登录按钮,让用户点击 授权按钮登录
_this.setData({
isHidden:0
})
}
}else{
//如果用户是已经授权过的
let token = app.globalData.token;
if(token){
//如果 token 存在
_this.triggerEvent("userLoadFun", { "token":app.globalData.token });
}else{
//如果 token 不存在
//调用 auth model 中的 wxlogin 如果成功 就会记录 token
auth.wxlogin().then(() => {
return auth.wxCheckSession();
}).then(() => {
_this.setData({
"isHidden": 1
});
//用户登录成功,调用页面中的函数来获取初始化数据
_this.triggerEvent("userLoadFun", {"token":app.globalData.token});
});
}
}
}
})
},
onGotUserInfo:function(e){
//点击授权按钮
let _this = this;
auth.wxlogin().then(()=>{
return auth.wxCheckSession();
}).then(()=>{
_this.setData({
"isHidden":1
});
_this.triggerEvent("userLoadFun", { "token": app.globalData.token });
});
},
}
})
//model 层的代码 import { Auth } from “../../model/auth.js”; 这个文件是用来执行功能的一个类
import { Http } from '../utils/http.js';
let app = getApp();
class Auth extends Http{
setCode(code){
return this.request({
url:"login/setCode",
method:"post",
param:{
code:code
}
});
}
userLogin(iv, encryptedData){
return this.request({
url:"login/index",
method:"post",
param:{
iv,
encryptedData,
cache_key: wx.getStorageSync("cache_key")
}
})
}
wxlogin(){
let _this = this;
return new Promise(function(reslove,reject){
wx.login({
success(res){
if(res.code){
_this.request({
url:"login/setCode",
method:"post",
param:{
code:res.code
}
}).then((res)=>{//通过 login 得到 cache_key 其实就是 session_key 在后台的键值
wx.setStorageSync("cache_key", res.cache_key);
reslove();
});
}else{
reject();
}
},
})
});
}
//通过得到的 cache_key 可以得到用户的信息,传给后台,要么登录,要么新增用户
wxCheckSession(){
let _this = this;
return new Promise(function(reslove,reject){
wx.checkSession({
success() {
//session_key 未过期,并且在本生命周期一直有效
wx.getUserInfo({
withCredentials: true,
success: function (res) {
_this.userLogin(res.iv, res.encryptedData).then((res) => {
app.globalData.token = res.token;
app.globalData.isLogin = true;
reslove()
})
},
fail: function () {
reject();
_this.showToast('用户登录失败,请重试')
}
})
},
fail() {
reject();
// session_key 已经失效,需要重新执行登录流程
//重新登录
_this.wxlogin();
}
})
});
}
}
export { Auth };
封装的 http 基类的代码,用来做小程序的请求后台接口的基类
import { config } from "./config.js"
class Http{
constructor(){
this.baseUrl = config.baseUrl;
}
request({url,method="get",param={},header={}}){
this.showLoading();
return new Promise((resolve,reject)=>{
wx.request({
url: this.baseUrl + url,
method:method,
data:param,
header:header,
success:(res)=>{
if(res.data.code == 200){
this.hideLoading();
resolve(res.data.data);
}else{
this.hideLoading();
this.showToast(res.msg);
reject();
}
},
fail:(res)=>{
this.hideLoading();
this.showToast("网络请求出错,请重试");
reject();
}
})
})
}
showToast(msg){
wx.showToast({
title: msg,
image:"/images/error.jpg",
duration:1500,
mask:true
})
}
showLoading(){
wx.showLoading({
title: '连接中...',
})
}
hideLoading(){
wx.hideLoading()
}
}
export {Http}
page 页面;这里的 page 页面是一个获得优惠券的页面,领取时要用户的信息
<!--pages/user_get_coupon/index.wxml-->
<nav paramters= "{{ paramters }}" bindreturnback="returnback"></nav>
<view class="coupon-wrapper" style="margin-top:{{statusBarHeight+88}}rpx">
<block wx:for="{{couponList}}" wx:key="{{index}}">
<view class="c-wrapper">
<coupon-one ticketsPro="{{item}}"></coupon-one>
</view>
</block>
</view>
<auth binduserLoadFun="userLoadFun"></auth>
// pages/user_get_coupon/index.js
import { Coupon } from "../../model/coupon.js";
let coupon = new Coupon();
let app = getApp();
Page({
/**
- 页面的初始数据
*/
data: {
paramters:{
nav:1,
title:"领取优惠券",
returnback:1
},
statusBarHeight: app.globalData.statusBarHeight,
couponList:[]
},
/**
- 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
userLoadFun:function(e){
coupon.getCouponList().then((res)=>{
this.setData({
couponList:res
})
})
},
returnback:function(){
wx.navigateBack({
delta:1
})
},
/**
- 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
- 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
- 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
- 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
- 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
- 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
- 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})