web與APP之間的互動—WebViewJavascriptBridge

Chen發表於2019-02-16

在實際專案之中,經常會遇到app之中嵌入網頁的情況(Hybrid),就需要web網頁與原生app之間互動,比如獲取當前使用者資訊等。一種簡單的方式就是通過url引數來搞定,但是這種方式異常死板,所以有了jsbridge。
本文章旨在記錄WebViewJavascriptBridge的實現,如有錯誤,還請指正!如有需要了解jsbridge原理,請google。

需求:

/**
 * 函式描述:js呼叫webview事件
 *
 * jsBridge.callHandler(method, data, callBack(response));
 * @param method {string} 方法名
 * @param data {Object} 引數
 * @return {Object} 回撥
 */

/**
 * 函式描述:webView呼叫JS事件
 *
 * jsBridge.registerHandler(method, callBack(response));
 * @param method {string} 方法名
 * @return {Object} 回撥
 */
const JsBridge = {
    init: function (callback) {
        const u = navigator.userAgent;
        const isiOS = !!u.match(/(i[^;]+;( U;)? CPU.+Mac OS X/); //判斷手機系統
        if (!isiOS) {  //ios
            if (window.WebViewJavascriptBridge) {
                callback(WebViewJavascriptBridge)
            } else {
                //    註冊事件,WebViewJavascriptBridge載入完成時呼叫
                document.addEventListener(
                    `WebViewJavascriptBridgeReady`,
                    function () {
                        callback(WebViewJavascriptBridge)
                    },
                    false
                );
            }
        } else { //Android
            //    如果有WebViewJavascriptBridge,則直接返回callback
            if (window.WebViewJavascriptBridge) {
                return callback(WebViewJavascriptBridge);
            }
            //    如果有WVJBCallbacks,則向WVJBCallbacks中注入事件
            if (window.WVJBCallbacks) {
                return window.WVJBCallbacks.push(callback);
            }
            //    否則建立WVJBCallbacks
            window.WVJBCallbacks = [callback];
            const WVJBIframe = document.createElement(`iframe`);
            WVJBIframe.style.display = `none`;
            WVJBIframe.src = `wvjbscheme://__BRIDGE_LOADED__`;
            document.documentElement.appendChild(WVJBIframe);
            setTimeout(function () {
                document.documentElement.removeChild(WVJBIframe)
            }, 0)
        }
    },

    first: function () {
        const u = navigator.userAgent;
        const isiOS = !!u.match(/(i[^;]+;( U;)? CPU.+Mac OS X/);
        if (!isiOS) {
            const _this = this;
            _this.init(function (bridge) {
                bridge.init(function (message, responseCallback) {
                    responseCallback(data);
                })
            })
        }
    },

    registerHandler: function (name, fun) {
        const _this = this;
        _this.init(function (bridge) {
            bridge.registerHandler(name, fun);
        })
    },

    callHandler: function (name, data, fun) {
        const _this = this;
        _this.init(function (bridge) {
            bridge.callHandler(name, data, fun);
        })
    }
}

// 初始化
JsBridge.first();

相關文章