微信小程序webview?postmessage通信完整配置和使用
需求概述
在微信小程序中使用 web-view 組件與內(nèi)嵌網(wǎng)頁進(jìn)行雙向通信,主要通過 postMessage 實現(xiàn)。以下是完整的配置和使用方法:
通信指南
1. 基礎(chǔ)配置
小程序端配置
// app.json 或 page.json
{
"usingComponents": {},
"permission": {
"scope.webView": {
"desc": "用于網(wǎng)頁和小程序通信"
}
}
}網(wǎng)頁端配置
<!-- 內(nèi)嵌網(wǎng)頁需引入微信JS-SDK --> <script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script> <!-- 或使用官方最新版本 -->
2. 通信實現(xiàn)
方案一:小程序向網(wǎng)頁發(fā)送消息
小程序端代碼:
// page.js
Page({
data: {
webViewUrl: 'https://your-domain.com/page.html'
},
onLoad() {
// 通過 web-view 組件的 ref 發(fā)送消息
},
// 向網(wǎng)頁發(fā)送消息
sendToWebPage() {
const webview = this.selectComponent('#myWebview')
webview.postMessage({
data: {
type: 'from_miniprogram',
message: 'Hello from Mini Program!',
timestamp: Date.now()
}
})
},
// 接收網(wǎng)頁消息
onMessage(e) {
console.log('收到網(wǎng)頁消息:', e.detail.data)
// 處理網(wǎng)頁發(fā)送的數(shù)據(jù)
const { type, data } = e.detail.data
if (type === 'from_web') {
// 處理邏輯
}
}
})<!-- page.wxml -->
<web-view
id="myWebview"
src="{{webViewUrl}}"
bindmessage="onMessage"
bindload="onWebViewLoad"
/>
<button bindtap="sendToWebPage">發(fā)送消息到網(wǎng)頁</button>網(wǎng)頁端代碼:
// 監(jiān)聽小程序消息
document.addEventListener('message', function(e) {
const data = e.data
console.log('收到小程序消息:', data)
// 處理消息
if (data.type === 'from_miniprogram') {
// 執(zhí)行相應(yīng)操作
// 回復(fù)消息給小程序
if (window.wx && window.wx.miniProgram) {
window.wx.miniProgram.postMessage({
data: {
type: 'from_web',
reply: 'Message received!',
original: data.message
}
})
}
}
})
// 主動發(fā)送消息到小程序
function sendToMiniProgram() {
if (window.wx && window.wx.miniProgram) {
window.wx.miniProgram.postMessage({
data: {
type: 'user_action',
action: 'button_click',
value: 'some_value',
timestamp: new Date().getTime()
}
})
}
}3. 完整通信示例
雙向通信封裝
小程序端封裝:
// utils/webviewBridge.js
class WebViewBridge {
constructor(webviewRef) {
this.webview = webviewRef
this.messageHandlers = new Map()
}
// 發(fā)送消息到網(wǎng)頁
postMessage(type, data) {
if (!this.webview) return false
this.webview.postMessage({
data: {
type,
payload: data,
timestamp: Date.now(),
source: 'miniprogram'
}
})
return true
}
// 注冊消息處理器
onMessage(type, handler) {
this.messageHandlers.set(type, handler)
}
// 處理接收到的消息
handleMessage(event) {
const { type, payload, source } = event.detail.data
if (source === 'web') {
const handler = this.messageHandlers.get(type)
if (handler) {
handler(payload)
}
}
}
// 移除處理器
offMessage(type) {
this.messageHandlers.delete(type)
}
}
export default WebViewBridge網(wǎng)頁端封裝:
// webview-bridge.js
class MiniProgramBridge {
constructor() {
this.handlers = new Map()
this.init()
}
init() {
// 監(jiān)聽小程序消息
document.addEventListener('message', (e) => {
const { type, payload, source } = e.data
if (source === 'miniprogram') {
this.dispatch(type, payload)
}
})
// 監(jiān)聽頁面卸載
window.addEventListener('beforeunload', () => {
this.postMessage('page_unload', {})
})
}
// 發(fā)送消息到小程序
postMessage(type, data) {
if (window.wx && window.wx.miniProgram) {
window.wx.miniProgram.postMessage({
data: {
type,
payload: data,
timestamp: Date.now(),
source: 'web'
}
})
return true
}
return false
}
// 注冊消息處理器
on(type, handler) {
if (!this.handlers.has(type)) {
this.handlers.set(type, [])
}
this.handlers.get(type).push(handler)
}
// 分發(fā)消息
dispatch(type, data) {
const typeHandlers = this.handlers.get(type)
if (typeHandlers) {
typeHandlers.forEach(handler => handler(data))
}
}
// 移除處理器
off(type, handler) {
const typeHandlers = this.handlers.get(type)
if (typeHandlers) {
const index = typeHandlers.indexOf(handler)
if (index > -1) {
typeHandlers.splice(index, 1)
}
}
}
}
// 創(chuàng)建全局實例
window.MiniProgramBridge = new MiniProgramBridge()4. 使用示例
小程序頁面使用:
import WebViewBridge from '../../utils/webviewBridge'
Page({
data: {
url: 'https://example.com'
},
onLoad() {
// 在 web-view 加載完成后初始化
},
onWebViewLoad() {
const webview = this.selectComponent('#webview')
this.bridge = new WebViewBridge(webview)
// 注冊消息處理器
this.bridge.onMessage('user_login', (data) => {
console.log('用戶登錄:', data)
// 處理登錄邏輯
})
this.bridge.onMessage('payment_success', (data) => {
console.log('支付成功:', data)
wx.showToast({
title: '支付成功'
})
})
},
// 發(fā)送用戶信息到網(wǎng)頁
sendUserInfo() {
this.bridge.postMessage('user_info', {
userId: '123',
nickname: '張三',
avatar: 'url'
})
}
})網(wǎng)頁端使用:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<button onclick="sendMessage()">發(fā)送消息到小程序</button>
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
<script src="webview-bridge.js"></script>
<script>
// 監(jiān)聽小程序消息
MiniProgramBridge.on('user_info', (data) => {
console.log('收到用戶信息:', data)
document.getElementById('user-name').innerText = data.nickname
})
// 發(fā)送消息到小程序
function sendMessage() {
MiniProgramBridge.postMessage('button_click', {
buttonId: 'submit',
value: 'confirmed'
})
}
// 頁面加載完成通知小程序
window.addEventListener('load', () => {
MiniProgramBridge.postMessage('page_loaded', {
title: document.title,
url: window.location.href
})
})
</script>
</body>
</html>5. 最佳實踐
// 1. 添加消息類型常量
const MessageTypes = {
USER_INFO: 'user_info',
PAYMENT: 'payment',
NAVIGATION: 'navigation',
ERROR: 'error'
}
// 2. 添加超時處理
function postMessageWithTimeout(type, data, timeout = 5000) {
return new Promise((resolve, reject) => {
const timer = setTimeout(() => {
reject(new Error('Message timeout'))
}, timeout)
// 發(fā)送消息邏輯
})
}
// 3. 錯誤處理
try {
webview.postMessage(data)
} catch (error) {
console.error('發(fā)送消息失敗:', error)
// 重試或降級處理
}6. 注意事項
1.確保網(wǎng)頁域名已在小程序后臺配置
2.處于安全性的考慮,始終驗證接收到的數(shù)據(jù),并且避免執(zhí)行不可信的腳本,防止xss攻擊
3.避免高頻發(fā)送(>100條/秒)
4.確保網(wǎng)頁端微信JS-SDK版本兼容
5.微信小程序 WebView 的 bindmessage 事件有一個延遲觸發(fā)機(jī)制,網(wǎng)頁向小程序發(fā)送的消息不會立即觸發(fā) bindmessage,而是在特定時機(jī)批量觸發(fā)。網(wǎng)頁向小程序 postMessage 時,會在以下特定時機(jī)觸發(fā)并收到消息:小程序后退、組件銷毀、分享、復(fù)制鏈接。e.detail = { data },data是多次 postMessage 的參數(shù)組成的數(shù)組。微信小程序webview官方文檔
7.實時通信方案
最佳實踐:對于需要實時通信的場景,應(yīng)該使用 WebSocket、URL 參數(shù)、Storage 輪詢等替代方案,bindmessage 更適合作為最終的數(shù)據(jù)提交機(jī)制。
// 方案1:使用URL參數(shù)傳遞狀態(tài)(實時)
// 網(wǎng)頁端
function updateState(state) {
// 通過修改hash或reload傳遞數(shù)據(jù)
window.location.hash = 'state=' + encodeURIComponent(JSON.stringify(state))
// 或者使用URL參數(shù)
const newUrl = window.location.pathname + '?data=' + encodeURIComponent(JSON.stringify(state))
window.history.replaceState({}, '', newUrl)
}
// 方案2:使用Storage同步(需要輪詢)
// 網(wǎng)頁端
function sendViaStorage(data) {
localStorage.setItem('web_to_miniprogram', JSON.stringify({
data,
timestamp: Date.now()
}))
}
// 小程序端(需要輪詢)
setInterval(() => {
const storage = wx.getStorageSync('web_to_miniprogram')
if (storage) {
this.handleMessage(storage.data)
wx.removeStorageSync('web_to_miniprogram')
}
}, 100)
// 方案3:使用WebSocket(真正實時)
const ws = new WebSocket('wss://your-server.com')
ws.onmessage = (e) => {
// 小程序通過后端中轉(zhuǎn)消息
}使用URL 參數(shù)為什么能達(dá)到實時的效果?
使用 URL 參數(shù) 可以達(dá)到實時效果,是因為 WebView 的 URL 變化會立即觸發(fā)小程序端的 bindload 事件(頁面加載或重載),而 bindload 是實時觸發(fā)的。這與 bindmessage 的延遲觸發(fā)機(jī)制完全不同。
拓展
什么是webview?它的作用是什么?
WebView(網(wǎng)頁視圖)可以簡單理解為一個嵌入在應(yīng)用程序(App或者小程序)內(nèi)部的“瀏覽器”。它不是一個獨立的瀏覽器(如 Chrome 或 Safari),而是一個讓 App或者小程序 能夠顯示和處理網(wǎng)頁內(nèi)容的控件或組件。
webview是“原生”與“網(wǎng)頁”的結(jié)合體
在移動和桌面應(yīng)用開發(fā)中,通常有兩種開發(fā)方式:
- 原生開發(fā) (Native): 為特定平臺(如 iOS、Android或者小程序)專門編寫的代碼,性能最好,但開發(fā)成本高。
- Web 開發(fā): 使用 HTML、CSS 和 JavaScript 編寫的網(wǎng)頁,跨平臺能力強(qiáng),但性能相對較弱。
WebView 處于兩者之間。它允許開發(fā)者在原生 App或者小程序 中嵌入網(wǎng)頁內(nèi)容。例如,你在一個電商 App 里看到的商品詳情頁,其實可能就是一個加載了網(wǎng)頁的 WebView,而不是用原生代碼畫出來的界面。
WebView 的作用非常廣泛,主要體現(xiàn)在以下幾個方面:
實現(xiàn)混合式開發(fā) (Hybrid Development)
這是 WebView 最主要的作用。很多 App或者小程序的頁面并不是完全用原生代碼寫的,而是部分界面使用 WebView 加載網(wǎng)頁。
- 優(yōu)勢: 開發(fā)者可以使用一套網(wǎng)頁代碼(HTML/JS),同時在 Android 和 iOS 或者小程序上運行,大大降低了開發(fā)和維護(hù)成本。
- 常見框架: 像 uni-app、React Native 等框架底層都利用了 WebView 技術(shù)。
動態(tài)更新,無需發(fā)版
這是 WebView 相比原生代碼的巨大優(yōu)勢。
- 原生 App或者小程序: 如果想修改界面或邏輯,必須修改代碼 -> 重新打包 -> 提交平臺審核 -> 用戶下載更新。
- WebView: 只需要在服務(wù)器端更新網(wǎng)頁代碼(HTML/JS),下次用戶打開頁面時,看到的就是最新的內(nèi)容,用戶無需重新下載安裝 App。這非常適合需要頻繁更新活動頁面(如促銷、廣告頁)的場景。
強(qiáng)大的交互能力
WebView 不僅僅是一個“看”網(wǎng)頁的工具,它還能和原生系統(tǒng)進(jìn)行深度交互(Native-Web 互操作):
- 調(diào)用系統(tǒng)功能: 網(wǎng)頁可以通過 WebView 調(diào)用手機(jī)的攝像頭、相冊、地理位置(GPS)等原生功能。
- 數(shù)據(jù)互通: 原生代碼可以往網(wǎng)頁里傳數(shù)據(jù),網(wǎng)頁也可以把用戶操作的結(jié)果回傳給原生代碼。
跨平臺兼容
在 Windows、macOS、Android、iOS 等不同平臺上,WebView 都能提供一致的網(wǎng)頁渲染體驗。例如,Microsoft Edge WebView2 控件允許開發(fā)者在桌面應(yīng)用中使用最新的 Chromium 引擎渲染網(wǎng)頁。
簡單來說,WebView 就是 App 里的一個“窗口”,用來展示網(wǎng)頁內(nèi)容。它的核心價值在于:讓 App 既能擁有原生的系統(tǒng)權(quán)限和性能,又能具備網(wǎng)頁的靈活更新和跨平臺能力。你在日常使用 App 時,那些偶爾需要“加載”的頁面,或者下拉刷新就能看到新內(nèi)容的界面,很大概率都是 WebView 在背后工作。
總結(jié)
到此這篇關(guān)于微信小程序webview postmessage通信完整配置和使用的文章就介紹到這了,更多相關(guān)微信小程序webview postmessage通信內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
一文讓你徹底弄懂js中undefined和null的區(qū)別
JavaScript是一門動態(tài)類型語言,元素除了表示存在的空值外,還有可能根本就不存在,這就是undefined存在的原因,這篇文章主要給大家介紹了關(guān)于undefined和null區(qū)別的相關(guān)資料,需要的朋友可以參考下2022-03-03
JS實現(xiàn)頭條新聞的經(jīng)典輪播圖效果示例
這篇文章主要介紹了JS實現(xiàn)頭條新聞的經(jīng)典輪播圖效果,涉及javascript圖片輪播切換相關(guān)實現(xiàn)技巧,需要的朋友可以參考下2019-01-01
JavaScript中常用的字符串方法函數(shù)操作方法總結(jié)
這篇文章主要介紹了JavaScript中所有的字符串函數(shù)操作方法整理匯總,包括字符串的長度、連接、查找、截取、替換、分隔、轉(zhuǎn)換等處理方法,以及網(wǎng)址中獲取文件名等等,需要的朋友可以參考下2023-12-12

