web-view加载h5页面实现授权登录
web-view 文档
https://developers.weixin.qq.com/miniprogram/dev/component/web-view.html#功能描述
场景描述
在微信小程序中,使用 组件 web-view 嵌入 h5 页面。
目的描述
- 在 h5 页面中获取 小程序临时登录凭证 cdoe;
- 在 h5 页面通过 小程序code 请求后端登录接口,拿到token
遇到的问题
- 微信小程序组件
web-view不能与 h5 页面进行实时通信; - h5 网页向小程序 postMessage 时,会在以下特定时机触发并收到消息:小程序后退、组件销毁、分享、复制链接(2.31.1)。e.detail = { data },data是多次 postMessage 的参数组成的数组。
实现思路
<web-view src="http://127.0.0.1:8080/index.html?openid=123456" bindmessage="onPostMessage" />- 小程序向 h5 页面传递数据,通过 url 携带参数;
- h5 页面向小程序传递数据,通过
bindmessage="onPostMessage",后面有详细代码; - 小程序定义全局变量 code ,目的是 当用户在 h5 页面点击登录按钮时,跳转小程序页面,相当于重新加载了小程序当前页面,此时会触发 小程序的方法
postMessage() - 小程序定义全局变量 codeChange ,以变量的形式 存储 方法;
- 小程序定义全局方法 triggerCodeChange ,
- 小程序
web-view组件页面,onLoad()生命周期中注册监听函数:getApp().globalData.codeChange = this.onCodeChange.bind(this); - h5 页面点击登录按钮,执行
wx.miniProgram.postMessage()函数,同时需要 跳转小程序当前页,以触发小程序postMessage(); - 小程序
web-view组件页面执行函数postMessage(),行进小程序授权,拿到 code 并全局储存,然后 触发监听函数triggerCodeChange(), - 小程序监听函数
triggerCodeChange()会执行之前注册的函数onCodeChange(), 函数内 将 code 更新到web-view的 url 链接,从而达到刷新的目的; - 此时在 h5 页面,通过 jQuery 就可以拿到路由参数 code 了,至于其他操作,则根据自己的需求去开发了。
TIP
注意: 如果理解困难,可以用两组页面来做,方便理解
// /pages/login/login
// 登录页
<web-view src="http://127.0.0.1:8080/login.html?code=123456" bindmessage="onPostMessage" />// /pages/index/index
// 首页
<web-view src="http://127.0.0.1:8080/index.html?code=123456" bindmessage="onPostMessage" />监听全局变量变化,参考: 微信小程序页面监听全局变量变化
小程序页面
/app.ts
ts
// app.ts
App<IAppOption|any>({
globalData: {
code:'',
codeChange: () => {},
},
// 触发监听器函数的方法
triggerCodeChange: function () {
this.globalData.codeChange()
}
})/pages/test/test.ts
ts
// pages/test/test.ts
Page({
data: {
url: 'http://127.0.0.1:8080/index.html'
},
onLoad() {
// 注册监听器函数
getApp().globalData.codeChange = this.onCodeChange.bind(this)
},
onCodeChange: function() {
// 全局变量 code 的值发生改变时,调用该函数
this.setData({
url: this.data.url + '?code=' + getApp().globalData.code
})
},
onPostMessage(e:any){
// h5 页面传递回来的数据
console.log(e, 'e - onPostMessage');
wx.login({
success: (res) => {
if (res.code) {
// 拿到 code 后,重载 h5 ,携带 code 在 h5 请求后端登录接口
// 全局储存 code
getApp().globalData.code = res.code
// 触发监听函数
getApp().triggerOpenidChange()
}
}
})
}
})/pages/test/test.wxml
html
<web-view src="{{ url }}" bindmessage="onPostMessage" />注意
bindmessage=onPostMessage() 触发机制:
网页向小程序 postMessage 时,会在以下特定时机触发并收到消息:小程序后退、组件销毁、分享、复制链接(2.31.1)。e.detail = { data },data是多次 postMessage 的参数组成的数组。
h5 页面
微信 jssdk 地址:
https://res.wx.qq.com/open/js/jweixin-1.3.1.js
/index.html
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="./js/jquery-3.6.4.min.js"></script>
<script src="https://res.wx.qq.com/open/js/jweixin-1.3.1.js"></script>
</head>
<body>
<button class="logon" onclick="login()">登录</button>
</body>
<script>
$(function(){
var uriObj = getSearch();
if (uriObj.code) {
alert(uriObj.code)
// todo 拿到了 code 后,用 ajax 向后端请求登录接口
// ...
}
})
function login(){
console.log('login');
wx.miniProgram.postMessage({
data: 'abcd', // 传递小程序需要的值
})
// 利用页面跳转 触发 小程序的方法 bindmessage=onPostMessage()
wx.miniProgram.reLaunch({
url: '/pages/test/test'
})
}
// 拿 url 参数,并组成 json 对象
function getSearch() {
var s = {};
var ls = location.search;
if (ls) ls = ls.slice(1);
ls.split('&').forEach(p => {
var [k, v] = p.split('=');
s[k] = v ? decodeURIComponent(v) : '';
});
return s;
}
</script>
</html>