項目背景:開發工具爲HBuilderX,框架爲uniapp,開發移動端的Web應用,在企業微信中使用(自建應用),Web開發的應用,不是小程序。
需求:頁面中用到<web-view>
組件,加載其他系統的頁面(有跨域),需要在父子頁面之間相互通信。這裏通信的東西其實就是獲取定位,通過uniapp獲取用戶定位信息,傳遞給<web-view>
內的頁面用於地圖的展示和其他業務需求。獲取定位也是遇到了一些問題,參考另一篇記錄《uniapp企業微信應用中的定位問題》
<web-view :src="https://****"></web-view>
<web-view>
內部其實就是iframe,因此本質上也就是要實現iframe的(跨域)父子通信。
原始方案:URL傳遞
在uniapp中獲取定位數據,通過URL參數的方式傳遞給<web-view>
的頁面。
<web-view :src="https://****?&longitude=${longitude}&latitude=${latitude}"></web-view>
這個方法弊端很多,不得不拋棄。
- 🚫性能影響&用戶體驗:很多時候
<web-view>
內的子頁面是不需要該定位數據的,只要當有用到地圖組件時,才需要獲取定位。這種方式不管要不要,都處理(獲取、發送),很影響性能,而且企業微信中獲取定位會彈出定位授權提示。 - 🚫重複加載頁面,而且會導致
<web-view>
加載多次,因爲獲取定位是異步的,參數變化會影響url(src)的變更,觸發頁面重新加載。
web-view相互通信
優化目標是在需要加載地圖組件時,向父頁面(uniapp)發送請求指令,父頁面(uniapp)獲取定位信息後,發送給子頁面,按需獲取。
基本的技術思路就是利用window/uni
的postMessage
、onmessage
來實現相互通信。但實際上由於uniapp面向各種不同的場景,如小程序、移動App、企業微信H5應用,實現方式略有不同,網上各種方案不一定行得通,因此記錄一下解決過程。
在子頁面發送指令
子頁面給父頁面(uniapp)發送指令,請求獲取定位信息,使用了uniapp提供的一個SDK來實現。
window.uni.postMessage()
方法發送指令信息。window.onmessage
事件接收消息。
mounted() {
// 發送消息指令
window.uni.postMessage({ data: { type: 'getLocation' } })
// 等待接收消息
window.onmessage = (e) => {
if (e.data?.getLocation) {
console.log('e.data?.getLocation', e.data.getLocation)
this.point = e.data?.getLocation
this.asyncInitMap()
}
}
},
這裏的uni
是uniapp
提供的一個SDK,在程序中引用JS文件。
<script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></script>
在uniapp父頁面中接收、響應
window.onmessage
事件接收消息指令,判斷是否約定的指令。- 獲取定位併發送,發送通過
this.$refs.webview.iframe.contentWindow.postMessage(res, url)
方法發送定位結果給子頁面。 - 注意的是,第一個參數爲要發送的數據,第二個參數爲目標域名,否則會發送失敗(不同域名)。
<template>
<web-view :src="src" ref="webview"></web-view>
</template>
<script>
import webview from './webview'
import getLocation from './Location.js'
export default {
mixins: [webview],
data() {
return {
src: '',
};
},
onLoad(options) {
this.src = 'http://****/q=**'
//接收指令
window.onmessage = (e) => {
//判斷指令
if(e.data?.data?.arg?.type === 'getLocation'){
//獲取定位併發送過去
getLocation().then(res => {
this.$refs.webview.iframe.contentWindow.postMessage({getLocation:res},this.webviewServer)
}).catch(err => console.log(err))
}
}
},
}
</script>
這一步藉助了chartGPT(3.5版本)的幫助,當然也是經過多輪對話才找到一點可用的,直接問他uniapp中的webview
通信方式,答案也不靠譜。
參考資料
- uniapp企業微信應用中的定位問題
- chartGPT
©️版權申明:版權所有@安木夕,本文內容僅供學習,歡迎指正、交流,轉載請註明出處!原文編輯地址-語雀