Uniapp页面和Web/H5网页的数据通信 vue2+uniapp中内嵌web-view页面消息交互 单点登录消息传递_web-view 和 页面进行通信
问题背景:
在工作过程中,遇到单点登录的需求,需要在uniapp开发的小程序中实现单点登录的功能,具体实现是在uniapp应用中,添加一个web-view页面,链接到单点登录的地址,在登录成功以后,向小程序发送token,小程序接收到token,完成小程序的登录。
实现步骤:
- 小程序新建web-view页面,链接到进行登录操作的网页
- 网页完成登录操作,登录成功向小程序发送的token
- 小程序接收到token,存储到localStorage,后续就可以使用token进行接口请求了
其中的难点就是要实现Uniapp页面和Web网页之间的消息传递,下面一起来看看我是怎么实现的吧~
步骤一:小程序添加web-view页面,嵌套登录的网址
新建一个webView.vue文件,里面只需要放置一个web-view组件,其中src属性赋值为你要嵌套显示的网页网址。
如果是单点登录的需求的话,webUrl应该是你进行登录的地址,一般来说登录地址后面还需要拼接一个重定向的地址,登录后会跳转到指定的重定向url,并且会携带登录的标识,一般是token或者code。
比如:https://xxxlogin.com?t=${new Date().getTime()}&redirect_uri=https://redirectPage?token=token-xxxxxxxxxxxxxxxxx
export default { data() { return { // 嵌套的网页地址,示例:xxxlogin.com,添加一个时间戳后缀,实时更新渲染 webUrl: `https://xxxlogin.com?t=${new Date().getTime()}`, // 默认web-view会占满整个页面,如果需要的话可以在这里添加自定义样式 webviewStyles:{} } }}
步骤二:网页完成登录,并向小程序发送消息
1. 引入需要的 uni 需要的js文件
Tips:如果是在小程序中嵌入web-view页面,还需要引入 jweixin-1.4.0.js,如果是app环境,则不需要引入。无论如何uni.webview.1.5.6.js是必须的
uni.webview.js
最新版地址:https://gitcode.net/dcloud/uni-app/-/raw/dev/dist/uni.webview.1.5.6.js
写在 vue 项目的 public/index.html 文件下,并且需要写在标签的下面
2. 方法一:postMessage 向小程序发送消息
单点登录需求实现,需要在重定向的地址中页面中获取到登录成功的token,再传递给小程序
2.1 在vue文件中引入 uni 对象
// 页面中需要单独引入一次uni.webview.js文件// 我这里是把文件下载到了项目里,所以就直接引入项目中的js了import * as uni from \'@/utils/uni.webview.1.5.6\';
2.2 添加 UniAppJSBridgeReady 监听事件
如果通讯建立成功,就会触发打印出当前环境
UniAppJSBridgeReady 的使用 : web-view | uni-app官网
document.addEventListener(\'UniAppJSBridgeReady\', function() { uni.getEnv(function(res) { console.log(\'当前环境:\' + JSON.stringify(res)); }); });
2.3 网页向小程序发送消息
网页中 :调用 uni.postMessage / uni.webView.postMessage 发送数据
Tips:传递的消息信息必须在 data 这个对象中。在 的
message
事件回调 event.detail.data
中接收消息。
// 可以打印一下uni对象,如果其中有postMessage,可以直接调用uni.postMessagedocument.addEventListener(\'UniAppJSBridgeReady\', function() { uni.postMessage({ data: { token: \'token-xxxxxxxxxxxxxxxxx\' } }); });// 如果uni对象没有postMessage,一般就是 uni.webView 中会有postMessagedocument.addEventListener(\'UniAppJSBridgeReady\', function() { uni.webView.postMessage({ data: { token: \'token-xxxxxxxxxxxxxxxxx\' } }); });
完整代码:
// 页面中需要单独引入一次uni.webview.js文件// 我这里是把文件下载到了项目里,所以就直接引入项目中的js了import * as uni from \'@/utils/uni.webview.1.5.6\';export default { name: \'Index\', data() { return { }; }, mounted() { // 获取到你的token \'token-xxxxxxxxxxxxxxxxx\' const token = this.$route.query.token;; // 待触发 `UniAppJSBridgeReady` 事件后,即可调用 uni 的 API。 document.addEventListener(\'UniAppJSBridgeReady\', function() { uni.webView.postMessage({ data: { token: token } }); uni.getEnv(function(res) { console.log(\'当前环境:\' + JSON.stringify(res)); }); }); }, methods: { }};
2.4 小程序接收消息,使用@message
methods: { onMessage(evt) { // 网页向应用 postMessage 时,会在特定时机(后退、组件销毁、分享)触发并收到消息。 console.log(\'URL onMessage:\', evt.detail); }}
Tips:uniapp的官网说明中指出了 :网页向应用 postMessage 时,会在特定时机(后退、组件销毁、分享)触发并收到消息。也就是说,当小程序那个web-view的页面经过跳转页面、回退页面、分享页面等操作时,才会调用到 message 方法进行onMessage的数据打印
在页面回退以后,就能在控制台打印出消息的内容了,就实现web页面向小程序进行消息传递啦 ~ 如果你不想用户手动进行回退的操作,可以用下面的方法
3. 方法二:navigateTo 向小程序发送消息
3.1 在vue文件中引入 uni 对象,同2.1
3.2 添加 UniAppJSBridgeReady 监听事件,同2.2
3.3 网页向小程序发送消息
网页中 :调用 uni.navigateTo 跳转页面,发送数据
// 在UniAppJSBridgeReady中,添加navigateTo进行页面跳转document.addEventListener(\'UniAppJSBridgeReady\', function() { uni.navigateTo({ url: `/pages/my/webView?token=${token}` }); uni.getEnv(function(res) { console.log(\'当前环境:\' + JSON.stringify(res)); });});
3.3 小程序接收消息,使用onLoad生命周期
小程序中:onLoad 页面启动的生命周期 接收数据
onLoad(options) { console.log(\'options\', options); if (options && options.token){ // 打印token console.log(\'token\', options.token) // 存储token uni.setStorageSync(\'token\',options.token) // 提示登录成功 uni.showToast({ title: \'登录成功,请稍后\', duration: 1500, icon:\"none\" }) }}
使用方法二,网页会操作小程序跳转一次页面,触发 onLoad 这个生命周期,就可以在options中获取到携带的token值了,我这里写的跳转页面,是跳转到了原先的web-view页面进行接收,大家也可以写别的页面试试~
希望能帮到大家!这个方法虽然不用用户手动操作回退页面,但是还有个缺点就是交互不太好,页面需要进行跳转,这个没法解决,要是有大佬其他办法传递,也欢迎在评论区进行讨论,无比感谢!!!
参考资料:
web-view | uni-app官网
在web-view加载的本地及远程HTML中调用uni的API及网页和vue页面通讯 - DCloud问答