Abstract

This paper records many problems encountered by novice authors when using UNIApp to develop the project. Second, to achieve indirect real-time communication between webview and H5 page of wechat applet development.

Ridicule: worthy of being a big factory, is so rich and strong personality.

preface

Development tool: UniApp 3.1.22; Wechat applets developer tool Stable 1.05.2107090

Research and development Background: In the development of Alipay small program, WE found that WebView and H5 can communicate in real time, so we used many such interfaces in the development of H5 page. However, when the development of micro channel small program, surprised to find that it does not support real-time communication, worthy of the big factory, is so proud.

The body of the

H5 sends a message to the WebView

Because so far, the wx WeChat applet. MiniProgram. PostMessage () method can’t real-time communication, but only in a specific time (small back, component destroyed, sharing) message event trigger module, so in order to achieve the goal to find another way out.

Is there a way?

Of course, there are ways. Duh, otherwise there wouldn’t be this blog. I’ve seen solutions on the Internet. I’m just gonna go ahead and use it here. This is A way, the long way to use the official API of wx. MiniProgram. NavigateTo () method, from A page of H5 (named A) to open the second page B, We then call const Pages = getCurrentPages() on page B to get an instance of page A and close page B.

(I) The specific code is as follows:

1. Page A: Open an H5 page A through the web-view TAB

<template>
    <view>
        <web-view :src="src" @message="getMessage" ></web-view>
    </view>
</template>

<script>
    export default {
        data() {
            return {
                src: ' '}; },onLoad: function(option) {
            this.src = "http://127.0.0.1:8080/#/a";
        },
	methods: {
            getMessag(){},callback({  //Response, method}){
                console.log("callback.response: ", response); // display {name: "zhang SAN "}
                console.log("callback.method: ", method); / / display passToA}}};</script>

<style>
	
</style>

Copy the code

2. H5 page A: Do only one thing here, open a new page B

function passToWebView(){
    wx.miniProgram.navigateTo({
        url: "/pages/wxWebView/B? Name = zhang SAN"
    });
}
Copy the code

3. Page B: accepts the parameters and forwards them to page A

<template>
    <view>Communication...</view>
</template>

<script>
    export default {
        data(){
            return {
                prevPageResponse: {}}; },onLoad(option) {
            this.prevPageResponse = option;
            wx.navigateBack(); // Close the page immediately
        },
        onUnload(){ // The lifecycle of the call when the page is closed
            const pages = getCurrentPages();
            const prevPage = pages[pages.length - 2]; // The previous page is page A
            if(prevPage.$vm.callback ! =undefined) {
                prevPage.$vm.callback({
                    response: this.prevPageResponse,
                    method: "passToA"}); }}}</script>

<style>
</style>
Copy the code

(2) Disadvantages

The downside of doing this is that it will display page B, so there’s no other way to do this. If there is a better way, please feel free to advise.

2. Webview sends message to H5

It’s almost impossible to implement using the official API, and the newbie author hasn’t found it yet, nor does it seem to be online, because I haven’t.

However, after repeated attempts, I found a way to do this by h5 listening on the Hashchange event! The only way to use this solution is if the URL is hashmode, but if not, a similar solution can be found.

Three important things: This is not the official method! It’s not official! It’s not official!

So, there are risks. In the future, if the goose factory has trouble and updates this way, we can only XXXXX. However, there may be new solutions in time. What if some swan factory boss gets the hang of it and lets live communications go.

However, in the worst case scenario, this communication problem can be solved by providing services such as Websocket or polling in the background.

(I) Code implementation

1. Page A-update: After callback method receives callback parameters, communication H5 method is directly called

<template>
    <view>
        <web-view :src="src" @message="getMessage" ></web-view>
    </view>
</template>

<script>
    export default {
        data() {
            return {
                src: ' '.backupSrc: ' '
            };
        },
        onLoad: function(option) {
            this.src = "http://127.0.0.1:8080/#/a";
            this.backupSrc = this.src; // Save the original address, convenient for multiple communication, parameters will not be polluted.
        },
	methods: {
            getMessag(){},callback({  //Response, method}){
                console.log("callback.response: ", response); // display {name: "zhang SAN "}
                console.log("callback.method: ", method); / / display passToA
                
                let src = this.backupSrc;
                if (src.indexOf("?") < = -1) {
                    src += "?";
                } else {
                    src += "&";
                }
                src += "__callback=1&__callbackResponse=" + JSON.stringify(response);

                if (method) {
                    src += "&__callbackMethod=" + method;
                }
                
                src += "&" + Math.random(); // Avoid invalidation of hashchange with no SRC changes when multiple communications are required
                
                this.src = src; // Make hashchange listen for event execution by modifying SRC}}};</script>

<style>
	
</style>

Copy the code

2. H5 page A-update: Update passToWebView method to realize receiving return parameters

let hashchange = (method) = > {
	
    return new Promise((resolve, reject) = > {
        // When the webView SRC is modified, it will close the page,
        // Trigger postMessage for other pages, causing a chain reaction that triggers hashchange for other pages
        window.addEventListener('hashchange'.function(event){

            let callback = JSUtil.getQueryVariable("__callback");
            let callbackMethod = JSUtil.getQueryVariable("__callbackMethod");
            let callbackResponse = JSUtil.getQueryVariable("__callbackResponse");
            if (JSUtil.isNotEmpty(callback)) {
                if (callbackMethod == method 
                        || (JSUtil.isEmpty(callbackMethod) && JSUtil.isEmpty(method))) {

                    if (callbackResponse && typeof callbackResponse == 'string' && callbackResponse.indexOf("{") = =0) {
                            callbackResponse = JSON.parse(decodeURIComponent(callbackResponse));
                    }

                    if (callback == 1) {
                            resolve(callbackResponse);
                    } else{ reject(callbackResponse); }}}}); }); }function passToWebView(){
    wx.miniProgram.navigateTo({
        url: "/pages/wxWebView/B? Name = zhang SAN"
    });
    
    hashchange("passToA").then((res) = > {
        // This is just a demonstration, return the parameters, in real development, you can complete some operations in the applet page, pass in the result of the operation
        console.log(res); // display {name: "zhang SAN "}
    });
}

Copy the code

(2) Advantages

I don’t know if you noticed the advantage of this. That is, the parameters will not be exposed to the network during parameter transmission, but will only be transmitted within the customer, unless wechat webView itself has vulnerabilities, otherwise there is generally no risk of exposure. In this way, some sensitive information can be passed, such as tokens, secret keys and so on. That’s why I spent so much time implementing this way of passing parameters.

Third, mining pit

1, webView tag SRC path must not appear “//” path, otherwise the page will keep refreshing.

2. The callbackResponse received by Hashchange is automatically encoded and must be decodeURIComponent

Four, afterword.

If there is an official method, of course it is better. If there is a better method, please advise more.

Once again, consider the worst-case scenario. If this method fails, you can also provide websocket or polling services in the background to solve this communication problem.

Sometimes, the solution to the problem, often unexpected and within the system of knowledge, do not know how to try to solve the problem. Life is the same, need a little bit of courage, need a little bit of courage to realize the ideal, what if it comes true?