美文网首页
深挖一:移动端混合开发之hybrid

深挖一:移动端混合开发之hybrid

作者: 轩辕无枫 | 来源:发表于2018-12-28 10:58 被阅读0次

    一、序言

    滚滚长江东逝水,奔流到海不复回。
    不要问我为为啥要废这么一句话,其实还是感叹前端发展的迅猛,很多技术和工具都是一闪而逝。如长江之水一样,转瞬即逝。
    移动端开发的方式就是如此:
    从2010年后的安卓和ios活了之后,移动端app开发的程序员可谓是如过江之鲫,源源不绝。
    每年从培训班出来的程序员多达几万。笔者当时还想去参加ios培训呢。
    然而过了几年后,考虑到开发成本、维护成本等各方面因素。分端开发已经越来越被当做一个开发效率的瓶颈。
    现在让我看看解决这类问题的历程吧。

    二、混合框架的两种模式

    1. hybrid :运行时联系沙盒。
    2. native : 编译时原生ui。
      今天主要是讲解hybrid的发展历程。而native会在下期跟大家见面。

    三、hybrid

    首先大家要明白deepLink的概念,不懂的推荐去看一篇文章链接:
    点我去看deepLink
    deepLink主要有url schema 和Universal Links 两种。本文准备深层次去讲解下 url schema的工作原理。
    给出一个url schema的样例。

    1. dinglei://
    2. dinglei://getUserInfo

    是不是看起来很眼熟,对了url schema本身就是一种协议,而且其工作原理和http的ajax还有些类似,上个别人的图。

    ajax工作原理。
    我们可以看到ajax的url一改变,就会被浏览器所监测到,然后发送给服务器。这一过程会开启一个线程。当服务器完成相应和返回数据后,线程会开始把回调压入到宏任务中,等待执行。

    Attention Please!!!

    如果说url schema 本身也是一个 同种类型的处理方式,你会不会偷着乐。

    原谅我再次盗图:


    url shcema 配合沙盒的工作原理图

    请读者先记住以下几点:

    1. url schema 是app自身注册到手机系统里面的。其配置方式是工程项目下的info.plist里面配置的。在安装完成后,就已经保存在手机系统的协议列表中了。
    2. 当浏览器挂起这个url schema的请求时,第一接收方式系统本身,不是盒子!!!!
    3. 默认的链接如 weixin:// 盒子的操作都是发送给手机系统,然后手机系统回去列表上查,查到了会去通知对应的盒子做处理,一般是直接打开盒子。如果需要做其他操作,需要传参。
    4. 回调,依然是盒子获取盒子本身webview的全局对象,进行执行。

    好吧!让我先上第一部分的干货吧。如何通过url schema去跟native实现一些业务场景吧。

    window.testUrlSchemaGlobal = window.testUrlSchemaGlobal || {};
    
    
    // 建立链接  ios 和安卓不同
    function doConnection (url) {
      console.log(url);
        if (window.$plt.isMatch('ios')) {
            window.location = url;
        } else {
          setUrl(url);
        }
    };
    
    // 建立 安卓的 链接
    function setUrl(url) {
      const iframe = document.createElement('iframe');
      iframe.style.display = 'none';
      iframe.setAttribute('src', url);
      const d = () => {
        setTimeout(() => {
          document.body.removeChild(iframe);
        }, 1000);
      };
      document.body.appendChild(iframe);
    }
    
    // 构造url
    function getUrlByParams (params) {
      debugger
        var paramStr = '', url = 'scheme://';
        url += params.funcName + '?t=' + new Date().getTime(); //时间戳,防止url不起效
        if (params.callback) {
            url += '&callback=' + params.callback;
            delete params.callback;
        }
        if (params.param) {
            paramStr = typeof params.param == 'object' ? JSON.stringify(params.param) : params.param;
            url += '&param=' + encodeURIComponent(paramStr);
        }
        return url;
    };
    
    /**
     * 
     * @param {*} params 
     * funName 
     * callback   传递名称 存放到  全局对象 testUrlSchemaGlobal  共bridge 去调用
     */
    function requestHybrid (params) {
        //生成唯一执行函数,执行后销毁
        var tt = (new Date().getTime());
        var t = 'hybrid_' + tt;
        var tmpFn;
    
        //处理有回调的情况
        if (params.callback) {
            tmpFn = params.callback;
            params.callback = t;
            window.testUrlSchemaGlobal[t] = function (data) {
                tmpFn(data);
                delete window.testUrlSchemaGlobal[t];
            }
        }
        // 直接连接
        doConnection(getUrlByParams(params));
    };
    
    
    //获取版本信息,约定APP的navigator.userAgent版本包含版本信息:scheme/xx.xx.xx
    function  getHybridInfo() {
        var platform_version = {};
        var na = navigator.userAgent;
        var info = na.match(/scheme\/\d\.\d\.\d/);
    
        if (info && info[0]) {
            info = info[0].split('/');
            if (info && info.length == 2) {
                platform_version.platform = info[0];
                platform_version.version = info[1];
            }
        }
        return platform_version;
    };
    
    举个例子:
    requestHybrid({funcName:"dinglei",param:{isWeb:false},callback(){ console.log('callback') }});
    

    其流程是
    1.生成链接 scheme://dinglei?t=1545898661620&param=%7B%22isWeb%22%3Afalse%7D
    2.然后注册全局的callback时间撮到去全局对象 testUrlSchemaGlobal中。
    3.iframe去建立链接,传递信息。
    4.系统处理这个链接,并向盒子发送。
    5.盒子去处理相关任务,完成后调用全局的callback。

    但是肯定会有同学,疑惑每次都经过手机系统的调度中心,做个中间转换。不是很浪费资源吗。
    回答是yes啦。

    看到这里是不是有种豁然开朗的感觉,喜欢的同学给个赞,因为作为新人,您的点赞会是我持续写作的动力。
    但是你以为已经结束了吗?


    chaoxiao

    这只是最原始的交互方式,换而言之,在hybrid的方式中,这种事最low的。也是最直接的。

    先给大家介绍ios关于交互方式的发展流程。让大家有个直接的印象。

    • 1.有很多的app直接使用在webview的代理中通过拦截的方式与native进行交互,通常是通过拦截url scheme判断是否是我们需要拦截处理的url及其所对应的要处理的功能是什么。任意版本都支持。也即是我们上面所说的方案。
    • 2.iOS7之后出了JavaScriptCore.framework用于与JS交互,但是不支持iOS6,对于还需要支持iOS6的app,就不能考虑这个了。若需要了解,看最后的推荐阅读。
    • 3.WebViewJavascriptBridge开源库使用,本质上,它也是通过webview的代理拦截scheme,然后注入相应的JS。
      我们再来看看第三种交互方式。jsbridge。相信用过微信或者支付宝早起版本进行开发的同学。应该对这个东西很眼熟。让我们来看看它是怎么使用的。

    首先我们回忆下我们上面的链接方式,是每次都会建立一次链接,给手机系统的调度中心,手机调度中心传给app盒子,盒子来决定做什么事情。这样是耗性能的。这是上面大致的情况。
    让我思考下,什么时候是一定需要传给手机调度中心的?

    很简单在盒子外的h5中打开链接的时候,是希望进行跳转到某个页面,这个时候因为不在沙盒内,是必须要传递给手机调度中心的。而页面本身在盒子里面的时候,那直接传递给沙盒不是更好点?

    jsbridge就是干这件事情的,它除了第一次建立链接是传递给手机的调度中心,后面都是功过bridge直接监听url schema的。
    直接上代码来讲解:

    • 第一步建立链接

    function setupWebViewJavascriptBridge(callback) {
        //  WebViewJavascriptBridge   传递信息
        if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
         // 建立回调 等同于 全局回调。
        if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
        window.WVJBCallbacks = [callback];
      // 建立链接
        var WVJBIframe = document.createElement('iframe');
        WVJBIframe.style.display = 'none';
        WVJBIframe.src = 'scheme://__BRIDGE_LOADED__';
        document.documentElement.appendChild(WVJBIframe);
        setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
    }
    
    • 第二步注册方法

    WebViewJavascriptBridge.registerHandler(handlerName,
          function(data, callback) {
                    //alert('handlerName callback' + data);
                    responseCallback(data),
                    callback && callback({
                      errorCode: "0",
                       errorMessage: "成功"
                    })
    })
    
    • 第三步使用

    WebViewJavascriptBridge.callHandler(path, params);
    

    因为水平有限,暂时如此。后面等研究够了,会继续更新。

    参考

    相关文章

      网友评论

          本文标题:深挖一:移动端混合开发之hybrid

          本文链接:https://www.haomeiwen.com/subject/oimrlqtx.html