1. hybrid是什么,为何用hybrid?
(1)hybrid文字解释
- hybrid即“混合”,即前端和客户端的混合开发
- 需前端开发人员和客户端开发 人员配合完成
- 某些环节也可能涉及到server端
(2)存在价值,为何会用hybrid?
- 可以快速迭代更新,无需app审核,(需审核因为客户端代码会有访问手机隐私的信息,比如地理位置,开启相机等),很关键!
- 体验流畅(和Native的体验基本类似)
- 减少开发和沟通成本,双端公用一套代码
(3)webview
- 是app中的一个组件(app可以有webview,也可以没有)
- 用于加载h5页面,即一个小型的浏览器内核
(4)file://协议
- file协议加载本地的资源,断网也可以加载,非常快
- http(s)协议是加载远程的资源,断网不可以,慢
(5)hybrid实现流程
不是所有场景都适合hybrid:
- 使用native:体验要求极致,变化不频繁(如头条的首页)
- 使用hybrid:体验要求高,变化频繁(如头条的新闻详情页)
- 使用h5:体验无要求,不常用(如举报、反馈等页面)
具体实现:
- 前端做好静态页面(html,js,css),将文件交给客户端
- 客户端拿到前端静态页面,以文件形式存储在app中
- 客户端在一个webview中,使用file协议加载静态页面
2. 介绍一下hybrid更新和上线的流程?
- 分版本,有版本号,如201803211015
- 将静态文件压缩成zip包,上传到服务端
- 客户端每次启动,都去服务端检查版本号
- 如果服务端版本号大于客户端版本号,就去下载最新的zip包
- 下载完之后解压包,然后将现有文件覆盖
3. hybrid和h5的主要区别?
(1)优点:
- 体验更好,跟Native体验基本一致
- 可快速迭代,无需app审核
(2)缺点:
- 开发成本高。联调、测试、查bug都比较麻烦
- 运维成本高。参考更新上线流程
(3)适用场景
- hybrid:产品的稳定功能,体验要求高,迭代频繁(产品型)
- h5:单词的运营活动(如红包)或不常用功能(运营型)
4. 前端JS和客户端如何通讯?
新闻详情页适用于hybrid,前端如何获取新闻内容?
- 不能用ajax获取。第一,跨域;第二,速度慢
- 客户端获取新闻内容,然后JS通讯拿到内容,再渲染
(1)JS和客户端通讯的基本形式
- JS访问客户端能力,传递参数和回调函数
- 客户端通过回调函数返回内容
(2)schema协议简介和使用
schema协议是前端和客户端通讯的约定
例如微信schema协议: weixin://dl/scan 扫一扫
var iframe = document.createELement('iframe');
iframe.style.display = 'none';
iframe.src = 'weixin://dl/scan'; // iframe访问schema
var body = document.body || document.getElementsByTagName('body')[0];
body.appendChild(iframe);
setTimeout(function(){
body.removeChild(iframe); // 销毁iframe
iframe = null;
})
// 如果要加上参数和callback,那么就要这么写
window['_weixin_scan_callback'] = function(result){
alert(result)
}
// ...省略...
iframe.src = 'weixin://dl/scan?k1=v1&k2=v2&k3=v3&callback=_weixin_scan_callback'
(3)schema使用的封装
(function (windwo, undefined){
// 调用schema的封装
function _invoke(action, data, callback){
// 拼接schema协议
var schema = 'myapp://utils'
schema += '/' + 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; // iframe访问schema
var body = document.body || document.getElementsByTagName('body')[0];
body.appendChild(iframe);
setTimeout(function(){
body.removeChild(iframe); // 销毁iframe
iframe = null;
})
}
// 暴露给全局
window.invoke = {
share: invokeShare,
login: invokeLogin,
scan: invokeScan
}
// 分享
function invokeShare(data, callback){
_invoke('share', data, callback)
}
// 登录
function invokeLogin(data, callback){
_invoke('login', data, callback)
}
// 打开扫一扫
function invokeScan(data, callback){
_invoke('scan', data, callback)
}
// 傻瓜式调用,而且不用再自己定义全局函数
window.invoke.share({title: 'xxx', content: 'xxx'}, function(result){
if(result.errno === 0){
alert('分享成功')
} else {
// 分享失败
alert(result.message)
}
})
})(window)
(4)内置上线
- 将以上封装的代码打包,叫做invoke.js,内置到客户端
- 客户端每次启动webview,都默认执行invoke.js
- 本地加载,免去网络加载的时间,更快。
- 本地加载,没有网络请求,黑客看不到schema协议,更安全