實現webView和小程序通訊,webView和iframe通訊,而后以webView作為中轉站,實現webView中 的iframe和小程序通訊。


之前領導要求就打通webView、小程序和iframs三者之間的通訊做一份技術文檔說明,功能是做出來了,結果后面沒有接到那個項目,也就沒有繼續開發下去,但也值得記錄一下。

項目目標

實現webView和小程序通訊,webView和iframe通訊,而后以webView作為中轉站,實現webView中的iframe和小程序通訊。

需求確定

在商城小程序中以webView的形式引入客服聊天頁面IM,在IM中以iframe的形式嵌入第三方頁面,內容和樣式第三方自定義。iframe的操作需求整理如下:

  1. 跳轉到文章詳情

  2. 鏈接到另一個客服

  3. 跳轉到商品詳情

  4. 跳轉到商品購物車頁

  5. 跳轉到訂單詳情

  6. 發送消息

可以整理為三大類:1.小程序頁面跳轉2.向某一個客服發起會話3.在當前會話發送消息

實現

  1. webView和小程序通訊

    官方文檔對於web-view組件的描述是:承載網頁的容器。會自動鋪滿整個小程序頁面,個人類型的小程序暫不支持使用。所以在小程序中webView是不能以彈窗的形式或者占據頁面一部分和其它內容共存,這個特點微信小程序和支付寶小程序都具備。

    webView組件和小程序只能通過bindmessage事件綁定進行通訊,對於這個事件官方的描述是這樣的:網頁向小程序 postMessage 時,會在特定時機(小程序后退、組件銷毀、分享)觸發並收到消息。也就是說無論webView通過postMessage向小程序發送多少次消息,只要不是在特定的時機(小程序后退、組件銷毀、分享),小程序就不會收到webView的消息。

    通過以上兩點,我們可以確定小程序的當前頁面只有一個webView是有效內容,那小程序和webView之間的通訊最常用的也就是小程序進行頁面的跳轉了。

// 在webView頁面中引入微信JS文件
<script src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>
// 進行頁面跳轉
wx.miniProgram.navigateTo({
    url: '/pages/home2/index', // 小程序頁面路徑
})

  2. webView和內嵌的iframe頁面通訊

      兩者通過postMessage進行通訊,主要代碼如下

window.addEventListener('message', (event) => {
    if (window.parent !== event.source) { return }
    console.log(event, 'event');  //接收到的信息
    top.postMessage("發送給父級頁面的信息,可以為對象", '父級頁面url或者*');
}, false);

 

完整主要代碼

  1. 小程序

<WebView src="xxxx"></WebView>
  1. webView客服聊天頁面IM

// 在webView頁面中引入微信JS文件
<script src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>

let ua = navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i) == "micromessenger") {
    //ios的ua中無miniProgram,但都有MicroMessenger(表示是微信瀏覽器)
    wx.miniProgram.getEnv((res) => {
        if (res.miniprogram) {
            console.log("在小程序里");
            // 接收到消息
            window.addEventListener('message', this.fnTest, false);
        } else {
            console.log("不在小程序里");
        }
    })
} else {
    console.log('不在微信里');
}

fnTest = (event) => {
    let data = event.data;
    if (data.operation === 'msg') {
        // 在當前會話發送消息
        let r = Math.ceil(Math.random() * 100000)
        let uuid = this.state.memberData.memberId + Date.now() + r;
        let sendData = '';
        // 0視頻,1圖片,2文件,4文本,8富文本,103iframe
        switch (data.data.type) {
                // 消息類型處理
            case 103:
                sendData = data.data.iframeUrl;
                break;
        }
        // this.sendMessage IM中發送消息函數
        this.sendMessage(sendData, data.data.type, uuid);
    } else if (data.operation === 'action') {
        // 小程序頁面跳轉
        wx.miniProgram.navigateTo({
            url: data.data.url  //'/pages/home2/index'
        })
    } else if (data.operation === 'chat') {
        let code = StringUtils.getQueryString('code')
        let url = `index.html?code=${code}&otherId=7&sessionScope=1&userCode=${data.data.userCode}`
        // 向某一個客服發起會話
        window.app.router.push(url)
    }
}

  3. 第三方iframe頁面

<!-- 簡單的模擬html頁面 -->
<span class="btn" style="margin-left: 0">發送消息</span>
<span class="action" style="background: lightpink">跳轉頁面</span>
<span class="chat" style="background: lightseagreen">跟他聊聊</span>
window.addEventListener('message', (event) => {
   if (window.parent !== event.source) { return }
   console.log(event, 'event');  //接收到的信息
   top.postMessage("發送給父級頁面的信息,可以為對象", '父級頁面url或者*');
}, false);

// operation  操作類型string  msg:發送消息 ,action:跳轉頁面,chat:發起聊天
// type 消息類型string operation為msg時,0視頻,1圖片,2文件,4文本,8富文本,103iframe
// 其他具體參數另定
$('.btn').on('click', function () {
    top.postMessage({
        operation: 'msg',
        data: {
            data: '消息內容',
            type: 103,  //Number類型
            size: 110,  //Number類型
            name: '',  //文件名稱
            iframeUrl: 'https://dev.iservice.dtyunxi.cn/i-service/dev/iservice-customer-web-pc/test.html'
        },
    }, '*')
});
$('.action').on('click', function () {
    top.postMessage({
        operation: 'action',
        data: {
            url: '/pages/home2/index?xxx=xx', // 需要跳轉頁面
        }
    }, '*')
});
$('.chat').on('click', function () {
    top.postMessage({
        operation: 'chat',
        data: {
            userCode: '007',  // 客服工號
        }
    }, '*')
});

定義參數

參數名 類型 是否必填 描述
operation string 枚舉值:1. msg:發送消息 2.action:跳轉頁面 3.chat:發起聊天
data object  
data參數
參數名 類型 是否必填 描述
type number operation為msg時必填 0視頻,1圖片,2文件,4文本,8富文本,103iframe
size number type為2時必填 文件大小,默認為0
name string type為2時必填 文件名稱,默認為空
iframeUrl string type為103時必填 iframe路徑
data string operation為msg且type不為103時必填 type為0,1,2時,為視頻、圖片、文件的路徑,type為4,8時,為發送的內容
url string operation為action時必填 小程序跳轉路徑
userCode string operation為chat時必填 客服工號

支付寶小程序

小程序代碼
// .axml
<view class="page">
    <web-view src="xxxx" onMessage="onmessage"></web-view>
</view>

// .js
Page({
    onmessage(e){
        // 拿到webView數據,進行一系列事件處理
        console.log(e,'e')
    }
});
webView代碼
// 引入js
<script type="text/javascript" src="https://appx/web-view.min.js"></script>
<!-- 如該 H5 頁面需要同時在非支付寶客戶端內使用,為避免該請求404,可參考以下寫法 -->
<!-- 請盡量在 html 頭部執行以下腳本 -->
<script>
    if (navigator.userAgent.indexOf('AlipayClient') > -1) {
        document.writeln('<script src="https://appx/web-view.min.js"' + '>' + '<' + '/' + 'script>');
    }
</script>

componentWillUnmount() {
    // 離開頁面,清除監聽
    window.removeEventListener('message', this.fnTest, false);
}

fnTest = (event) => {
    // alert(JSON.stringify(event), 'event')
    let data = event.data;
    if (data.operation === 'msg') {
        // 在當前會話發送消息
        let r = Math.ceil(Math.random() * 100000)
        let uuid = this.state.memberData.memberId + Date.now() + r;
        let sendData = '';
        // 0視頻,1圖片,2文件,4文本,8富文本,103iframe
        switch (data.data.type) {
                // 消息類型處理
            case 103:
                sendData = data.data.iframeUrl;
                break;
        }
        // this.sendMessage IM中發送消息函數
        this.sendMessage(sendData, data.data.type, uuid);
    } else if (data.operation === 'action') {
        // 小程序頁面跳轉
        // my.navigateTo({ url: `../../${data.data.url}` });
        my.navigateTo({ url: `../test/test` });
    } else if (data.operation === 'chat') {
        let code = StringUtils.getQueryString('code')
        let url = `index.html?code=${code}&otherId=7&sessionScope=1&userCode=${data.data.userCode}`
        // 向某一個客服發起會話
        window.app.router.push(url)
    }
}

componentDidMount() {
    window.addEventListener('message', this.fnTest, false);
}

 

 特別說明:webView向支付寶小程序發送消息時,並沒有微信小程序接收webView消息的限制【需要在特定時機(小程序后退、組件銷毀、分享)觸發才能收到消息】,只要webView通過 my.postMessage(obj)向小程序發送消息,小程序就能接收到消息,支付寶小程序和webView的通訊更方便靈活。

 

流程圖

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM