不同源H5页面消息通信(web-view 内的H5向父级页面发消息并回传结果给子页面)

应用场景是两个 H5不同源 的情况下实现消息互通。

本示例使用 uniapp 开发H5,父级H5 通过 <web-view> 组件加载 子H5 页面;子H5 页面向 父级H5 发送消息调起 父级H5 页面的微信扫一扫功能,再将扫一扫结果回传给 子H5页面。

  • 父级H5链接:https://www.A.com
  • 子级H5链接:https://www.B.com

父级 H5 页面

  • index.vue
<template>
	<web-view allow="geolocation; microphone; camera; midi; encrypted-media;display-capture;" :src="url"></web-view>
</template>

<script src="./index.js"></script>

<style lang="scss" scoped>
	@import './index.scss';
</style>
  • index.js
import wx from "weixin-js-sdk";
// 请求后台接口
import {
    
     getJsapiConfig } '@/apis/wechatApi';

export default {
    
    
    data() {
    
    
        return {
    
    
            url: ''
        }
    },
	async onLoad() {
    
    
		const _this = this
		
		// 初始化微信Jsapi配置
		const url = window.location.href.split("#")[0]
        const {
    
    code, data: wxConfig} = await getJsapiConfig({
    
    url})
        if (code === 200) {
    
    
            await _this.initWxConfig(wxConfig);
        }
		
		// 监听消息(监听子H5页面发送过来的消息)
		window.addEventListener('message', async (event) => {
    
    
		    const {
    
    origin, data, source} = event
		    console.log('子页面消息:', origin, data, source)
			if (window === source) {
    
    
		        // 跳过第一次的初始化触发的情况
		        return
		    }
			// 过虑非子页面源的消息
		    if (origin !== 'https://www.B.com') {
    
    
		        return
		    }
			// 获取子页面自定义 cmd
		    const {
    
    cmd} = data
		    if (cmd !== 'wx.scanQRCode') {
    
    
		        return
		    }
		    const result = await _this.wxScanCode()
		    // 将扫一扫结果,发送回子页面
		    const response = {
    
    cmd: "wx.scanQRCodeResult", result}
		    await source.postMessage(response, origin);
		}, false);

		// 子 H5 页面链接地址
		this.url = 'https://www.B.com'
	},
	methods: {
    
    
		// 初始化微信配置
		initWxConfig(config) {
    
    
	        const {
    
    appId, timestamp, nonceStr, signature} = config
	        wx.config({
    
    
	            debug: false,
	            appId: appId,
	            timestamp: Number(timestamp),
	            nonceStr: nonceStr,
	            signature: signature,
	            jsApiList: ['scanQRCode']
	        })
	    },
		// H5调起微信扫一扫功能
		wxScanCode() {
    
    
	        return new Promise((resolve, reject) => {
    
    
	            wx.ready(() => {
    
    
	                wx.scanQRCode({
    
    
	                    needResult: 1,
	                    scanType: ["qrCode", "barCode"],
	                    success: async function (res) {
    
    
	                        const result = res.resultStr;
	                        resolve(result)
	                    },
	                    error: function (res) {
    
    
	                        reject(res)
	                    }
	                })
	            })
	            wx.error((res) => {
    
    
	                reject(res)
	            })
	        })
	    }
	}
}

子级 H5 页面

  • index.vue
<template>
	<view>{
   
   { result }}</view>
	<button @click="handleClick">调起父级页面微信扫一扫</button>
</template>

<script src="./index.js"></script>

<style lang="scss" scoped>
	@import './index.scss';
</style>
  • index.js
export default {
    
    
	data() {
    
    
        return {
    
    
			result: null
		}
	},
	async mounted() {
    
    
        const _this = this
		// 监听消息(监听父级H5页面传回来的消息)
		window.addEventListener('message', async (event) => {
    
    
            const {
    
    origin, data, source} = event
			if (window === source) {
    
    
                return
            }
			// 过虑非父级页面源的消息
            if (origin !== 'https://www.A.com') {
    
    
                return
            }
            const {
    
    cmd, result} = data
            if (cmd === 'wx.scanQRCodeResult') {
    
    
                _this.result = result
            }
        }, false);
	},
	methods: {
    
    
		handleClick() {
    
    
			// 向父级页面发消息
			window.parent.postMessage({
    
    cmd: 'wx.scanQRCode', data: {
    
    }}, 'https://www.A.com')
		}
	}
}