hybrid介绍

hybrid 即“混合”,是客户端(app)和前端混合开发,需要前端开发人员和客户端开发人员配合完成,某些环节也可能涉及到server端。
PS:不要以为自己是前端开发就不学习客户端或者server端的知识。

基础知识:

webview是app中的一个组件(app可以有webview,也可以没有),用于加载h5页面,即一个小型的浏览器内核。
在这里插入图片描述

schema协议是前端和客户端通讯的约定。每个app可能不一样,协议前面的名称都是app自己可以定的。比如:
在这里插入图片描述
在这里插入图片描述
前端要遵守这些协议才能和客户端交互,

file:// 协议是用来加载本地文件(html,css,js)用的协议,即使是断网了依然可以加载这些资源,加载速度快。hybrid用的就是file://协议,因为快,file://协议后面跟文件的绝对路径。

http(s)协议用来加载远程文件,需要网络,会相对慢点。

hybrid存在的价值:

  • 可以快速迭代,无需app审核。

审核再快都得一两天的样子,苹果strore审核得一个周的样子,但用了hybrid可以在不需要app审核得情况下一天上线很多次都没问题。app需要审核是因为开发app的代码有权利访问手机中涉及到用户安全和隐私的内容,比如深层次的api像地理位置、开启相机。hybrid用前端开发的那部分只是上线前端代码(html,css,js),前端代码是没有能力获取用户的地理位置、摄像头拍照扫码等信息的,反正前端代码没这么高的权限想捣乱都没办法就不用审核了。

  • 体验流畅(和NA体验基本类似)
  • 减少开发和沟通成本,双端公用一套代码

hybrid更新方法:

前端做好静态页面(html,js,css),将文件交给客户端,客户端拿到前端静态页面后以文件形式存储在app中,客户端在一个webview中使用file://协议加载静态文件。用户每次打开app,app都去server端看看有没有最新的前端静态文件,如果有就下载下来然后覆盖本地旧的前端静态文件,替换每个客户端的静态文件只能客户端来做,让客户端去server下载最新的静态文件,前端可以维护server的前端静态文件,把最新的前端文件上传给客户端。

  • 分版本,有版本好,如201910111015
  • 将静态文件压缩成zip包,上传到服务端
  • 客户端每次启动都去服务端检查版本号
  • 如果服务端版本号大于客户端版本号,就去下载最新的zip包
  • 下载完后解压包,然后将现有文件覆盖
    在这里插入图片描述

注意:服务端的版本和zip包的维护;用户在客户端更新zip包前先对比版本号,没必要启动一次下载一次;zip包下载解压和覆盖。

hybrid和h5的区别:

h5在加载的时候会有一小会儿的白屏,页面上方会出现一个加载条,但在hybrid中这些都没有。所以hybrid相对h5更快更流畅。hybrid产品功能稳定,体验要求高,迭代频繁。h5大多只在单次的运营活动或不常用功能。

前端和客户端通讯:

新闻详情页适用hybrid,前端获取新闻内容不能用ajax获取,ajax获取的接口是http(s)协议,而hybrid本地用的是file://协议,协议不一样会跨域,而且http(s)线上的地址速度慢。所以用客户端获取新闻内容(这里客户端是可以提前获取新闻内容的),然后js通讯拿到内容再渲染,
基本形式:
js访问客户端能力,传递参数和回调函数,客户端通过回调函数返回内容。

封装schema方便前端使用

invoke.js

//自执行函数,防止污染全局变量
(function (window, undefined) {

    // 调用 schema 的封装
    function _invoke(action, data, callback) {
        // 拼装 schema 协议
        var schema = 'myapp://utils/' + action

        // 拼接参数
        schema += '?a=a'
        var key
        for (key in data) {
            if (data.hasOwnProperty(key)) {
                schema += '&' + key + data[key]
            }
        }

        // 处理 callback
        var callbackName = ''
        if (typeof callback === 'string') {
            callbackName = callback
        } else {
            callbackName = action + Date.now()
            window[callbackName] = callback
        }
        schema += 'callback=callbackName'

        // 触发
        var iframe = document.createElement('iframe')
        iframe.style.display = 'none'
        iframe.src = schema  // 重要!
        var body = document.body
        body.appendChild(iframe)
        setTimeout(function () {
            body.removeChild(iframe)
            iframe = null
        })
    }

    // 暴露到全局变量
    window.invoke = {
        share: function (data, callback) {
            _invoke('share', data, callback)
        },
        scan: function (data, callback) {
            _invoke('scan', data, callback)
        }
        login: function (data, callback) {
            _invoke('login', data, callback)
        }
    }

})(window)

schema.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
    <title>Document</title>
</head>
<body>
    <button id="btn1">扫一扫</button>
    <button id="btn2">分享</button>

    <script type="text/javascript" src="./invoke.js"></script>
    <script type="text/javascript">
        // function invokeScan() {
        //     window['_invoke_scan_callback_'] = function (result) {
        //         alert(result)
        //     }

        //     var iframe = document.createElement('iframe')
        //     iframe.style.display = 'none'
        //     // iframe.src = 'weixin://dl/scan'  // 重要!
        //     iframe.src = 'weixin://dl/scan?k1=v1&k2=v2&k3=v3&callback=_invoke_scan_callback_'
        //     var body = document.body
        //     body.appendChild(iframe)
        //     setTimeout(function () {
        //         body.removeChild(iframe)
        //         iframe = null
        //     })
        // }

        document.getElementById('btn1').addEventListener('click', function () {
            // invokeScan()
            window.invoke.scan({}, function () {})
        })
        document.getElementById('btn2').addEventListener('click', function () {
            window.invoke.share({
                title: 'xxx',
                content: 'yyy'
            }, function (result) {
                if (result.errno === 0) {
                    alert('分享成功')
                } else {
                    alert(result.message)
                }
            })
        })
    </script>
</body>
</html>

内置上线:
将以上封装的invoke.js代码打包,内置到客户端,客户端每次启动webview都默认执行invoke.js,本地加载免去网络加载的时间,更快,本地加载没有网络请求黑客看不到schema协议,更安全。scheme协议就是用来规定前端和客户端如何进行通讯,它可以通过iframe来使用,内置上线的好出就是更快更安全。

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值