转:https://blog.csdn.net/CameloHuang/article/details/64476385

从html5打开本地的app–如果本地没有app就跳转到下载页面,大家都会认为这是一项很简单的操作。网上的教程也很多,但是可行性都不高。因为手机系统和浏览器型号各不相同,所以兼容性会是让各个前端工程师头疼的问题。我们不妨看一下京东是如何解决的。京东的原代码已经混淆过了,我只能一点点反混淆并注释。

网上的文章千篇一律 都是采用window.location.href的方式打开的,但是这种方法的兼容性非常的渣。在ios的safari浏览器中无法使用,会出现还未打开app就自动跳转到下载页面的情况,影响用户的使用。那么我们来看一下京东是如何解决兼容性的问题。 
下面附上我的代码翻译和注释。 
京东打开app的js代码链接

 (function(){
// 判断浏览器
var Navigator = navigator.userAgent;
var ifChrome = Navigator.match(/Chrome/i) != null && Navigator.match(/Version\/\d+\.\d+(\.\d+)?\sChrome\//i) == null ? true : false;
var ifAndroid = (Navigator.match(/(Android);?[\s\/]+([\d.]+)?/)) ? true : false;
var ifiPad = (Navigator.match(/(iPad).*OS\s([\d_]+)/)) ? true : false;
var ifiPhone = (!ifiPad && Navigator.match(/(iPhone\sOS)\s([\d_]+)/)) ? true : false;
var ifSafari = (ifiPhone || ifiPad) && Navigator.match(/Safari/);
var version = ;
ifSafari && (version = Navigator.match(/Version\/([\d\.]+)/)); version = parseFloat(version[], );
// 是否从微信打开
var ifWeixin = navigator.userAgent.indexOf("MicroMessenger") >= ; // weixin
var j = false;
var iframe = "plugIn_downloadAppPlugIn_loadIframe";
var t = false;
var i = ;
var B = {};
var b = {};
var selector = null;
var Hquery = {};
// 判断当前使用的js框架是zepto还是jquery
var Query = window.Zepto || window.jQuery ? true : false;
var g = [];
// 是否存在html5的localStorage 存储
var v = window.localStorage ? true : false;
var o = "mdownloadAppPlugInskip";
var p = null; function m() { // 打印时间 例如:2016-5-18
var M = new Date();
var N = M.getFullYear();
var O = M.getMonth() + ;
var L = M.getDate();
strDate = N + "-" + O + "-" + L;
return strDate
}
// 微信相关操作
function r() { // weixin api
WeixinJSBridge.invoke("getInstallState", {
packageName: "com.jingdong.app.mall",
packageUrl: "openApp.jdMobile://"
}, function(M) {
var N = M.err_msg,
L = ;
if (N.indexOf("get_install_state:yes") > -) {
j = true
}
})
}
// 根据是否存在js框架进行dom和时间的绑定
function bind(dom, event, fun) { // bind event
if (Query) {
selector("#" + dom).bind(event, fun)
} else {
selector("#" + dom).addEventListener(event, fun, !)
}
} function z(L) {
var M = (L || "mGen") + (++i);
return M
}
// 微信操作
if (ifWeixin) { // if navigitor is weixin
if (window.WeixinJSBridge && WeixinJSBridge.invoke) {
r()
} else {
document.addEventListener("WeixinJSBridgeReady", r, !)
}
} // 如果存在js框架
if (Query) {
selector = window.$;
Hquery = window.$
} else {
selector = function(obj) {
if (typeof obj == "object") {
return obj
}
return document.querySelector(obj);
};
if (!window.$) {
window.$ = Hquery = selector
} else {
Hquery = window.$
}
}
window.onblur = function() {
for (var L = ; L < g.length; L++) {
clearTimeout(g[L])
}
};
// 设置cookie。
function e(N) {
var M = document.cookie.indexOf(N + "=");
if (M == -) {
return ""
}
M = M + N.length + ;
var L = document.cookie.indexOf(";", M);
if (L == -) {
L = document.cookie.length
}
return document.cookie.substring(M, L)
}
// 设置cookie
function l(N, P, L, Q, O) {
var R = N + "=" + escape(P);
if (L != "") {
var M = new Date();
M.setTime(M.getTime() + L * * * );
R += ";expires=" + M.toGMTString()
}
if (Q != "") {
R += ";path=" + Q
}
if (O != "") {
R += ";domain=" + O
}
document.cookie = R
} // 打开的链接集合
function F(L) {
var url = {
downAppURl: "http://h5.m.jd.com/active/download/download.html?channel=jd-m",
downAppIos: "http://union.m.jd.com/download/go.action?to=http%3A%2F%2Fitunes.apple.com%2Fcn%2Fapp%2Fid414245413&client=apple&unionId=12532&subunionId=m-top&key=e4dd45c0f480d8a08c4621b4fff5de74",
downWeixin: "http://a.app.qq.com/o/simple.jsp?pkgname=com.jingdong.app.mall&g_f=991850",
downIpad: "https://itunes.apple.com/cn/app/jing-dong-hd/id434374726?mt=8",
inteneUrl: "openApp.jdMobile://360buy?type=1",
inteneUrlParams: null,
openAppBtnId: "",
closePanelBtnId: "",
closePanelId: "",
closeCallblack: null,
closeCallblackSource: null,
cookieFlag: null,
noRecord: false,
sourceType: "JSHOP_SOURCE_TYPE",
sourceValue: "JSHOP_SOURCE_VALUE",
openAppEventId: "MDownLoadFloat_OpenNow",
closePanelEventId: "MDownLoadFloat_Close"
};
if (L) {
for (var M in L) {
if (M && L[M]) {
url[M] = L[M]
}
}
}
return url
}
// 敲黑板 重点内容。看京东是怎么解决兼容问题的。
function openApp(N, L) { // openApp
var R = h(N); //获取相对应的url
var O = null;
if (ifWeixin) { // 如果是微信端
var M = null;
if (j) {
M = R
} else {
M = N.downWeixin
}
location.href = M; // 直接使用location.href打开
return
}
if (ifiPad) { // 如果是ipad
O = N.downIpad
} else {
if (ifiPhone) { // 如果是iphone
O = N.downAppIos
} else {
O = N.downAppURl
}
} if (ifChrome) { // 如果是chrome
if (ifAndroid) { //安卓浏览器
var Q = R;
R = y(Q);
// 延后50毫秒
setTimeout(function() {
window.location.href = R
}, )
}
}
if (ifSafari && version >= ) { // 判断safari版本 如果大于9
setTimeout(function() { // 必须要使用settimeout
var S = document.createElement("a"); //创建a元素
S.setAttribute("href", R), S.style.display = "none", document.body.appendChild(S);
var T = document.createEvent("HTMLEvents"); // 返回新创建的 Event 对象,具有指定的类型。
T.initEvent("click", !, !)// 初始化新事件对象的属性, S.dispatchEvent(T) // 绑定事件
}, )
} else {
document.querySelector("#" + iframe).src = R // 将iframe增加src
}
var P = Date.now();
setTimeout(function() {
if (L) {
var S = setTimeout(function() {
x(P, O)
}, );
g.push(S)
}
}, )
}
// x方法
function x(N, downUrl) {
var L = Date.now();
if (N && (L - N) < ( + )) {
window.location.href = downUrl
}
} function h(N) {
var V = [];
var P = N.inteneUrlParams;
var T = {
category: "jump",
des: "productDetail"
};
if (N.sourceType && N.sourceValue) {
T.sourceType = N.sourceType;
T.sourceValue = N.sourceValue;
if (P && !P.sourceType && !P.sourceValue) {
P.sourceType = N.sourceType;
P.sourceValue = N.sourceValue
}
}
if (P) {
for (var U in P) {
if (U && P[U]) {
V.push('"' + U + '":"' + P[U] + '"')
}
}
} else {
for (var U in T) {
if (U && T[U]) {
V.push('"' + U + '":"' + T[U] + '"')
}
}
}
try {
var Q = MPing.EventSeries.getSeries();
if (Q) {
var W = JSON.parse(Q);
W.jdv = encodeURIComponent(e("__jdv"));
W.unpl = encodeURIComponent(e("unpl"));
W.mt_xid = encodeURIComponent(e("mt_xid"));
W.mt_subsite = encodeURIComponent(e("mt_subsite"))
}
var S = {
mt_subsite: encodeURIComponent(e("mt_subsite")),
__jdv: encodeURIComponent(e("__jdv")),
unpl: encodeURIComponent(e("unpl")),
__jda: encodeURIComponent(e("__jda"))
};
Q = JSON.stringify(W);
V.push('"m_param":' + Q);
V.push('"SE":' + JSON.stringify(S))
} catch (R) {
V.push('"m_param":null')
}
var M = "{" + V.join(",") + "}";
var O = N.inteneUrl.split("?");
var L = null;
if (O.length == ) {
L = O[] + "?" + O[] + "&params=" + M
} else {
L = O[] + "?params=" + M
}
return L
} function y(L) {
return "intent://m.jd.com/#Intent;scheme=" + L + ";package=com.jingdong.app.mall;end"
} function n(L) {
if (L.openAppBtnId) {
B[L.openAppBtnId] = L;
G(L.openAppBtnId, L.openAppEventId);
bind(L.openAppBtnId, "click", function() {
var P = this.getAttribute("id");
var M = B[P];
if (!t) {
var N = document.createElement("iframe");
N.id = iframe;
document.body.appendChild(N);
document.getElementById(iframe).style.display = "none";
document.getElementById(iframe).style.width = "0px";
document.getElementById(iframe).style.height = "0px";
t = true
}
var O = M.cookieFlag ? "downloadAppPlugIn_downCloseDate_" + M.cookieFlag : "downloadAppPlugIn_downCloseDate";
l(O, Date.now() + "_2592000000", , "/", "m.jd.com");
l(O, Date.now() + "_2592000000", , "/", "m.jd.hk");
openApp(M, true)
})
}
} function D(M) {
if (M.closePanelBtnId && M.closePanelId) {
B[M.closePanelBtnId] = M;
G(M.closePanelBtnId, M.closePanelEventId);
var Q = M.cookieFlag ? "downloadAppPlugIn_downCloseDate_" + M.cookieFlag : "downloadAppPlugIn_downCloseDate";
var O = e(Q);
var P = null;
if (O) {
P = O.split("_");
if (P.length == ) {
P[] = parseInt(P[], );
P[] = parseInt(P[], )
} else {
P = null
}
}
var L = Date.now();
if (Html5Plus() || (!M.noRecord && P && P.length == && (L - P[]) < P[])) {
document.querySelector("#" + M.closePanelId).style.display = "none";
if (M.closeCallblack) {
var N = M.closeCallblackSource ? M.closeCallblackSource : null;
M.closeCallblack.call(N)
}
return
} else {
document.querySelector("#" + M.closePanelId).style.display = "block"
}
bind(M.closePanelBtnId, "click", function() {
var U = this.getAttribute("id");
var R = B[U];
var T = R.cookieFlag ? "downloadAppPlugIn_downCloseDate_" + R.cookieFlag : "downloadAppPlugIn_downCloseDate";
if (!R.noRecord) {
l(T, Date.now() + "_259200000", , "/", "m.jd.com");
l(T, Date.now() + "_259200000", , "/", "m.jd.hk")
}
document.querySelector("#" + R.closePanelId).style.display = "none";
if (R.closeCallblack) {
var S = R.closeCallblackSource ? R.closeCallblackSource : null;
R.closeCallblack.call(S)
}
})
}
} function Html5Plus() { // htmlplus
if (Navigator.indexOf("Html5Plus") >= ) {
return true
} else {
return false
}
} function G(P, M) {
try {
var O = document.getElementById(P);
var L = O.className;
if (L) {
L = L + " J_ping"
} else {
L = "J_ping"
}
O.className = L;
O.setAttribute("report-eventid", M)
} catch (N) {}
} function C(L) {
var M = F(L);
n(M);
D(M)
}
Hquery.downloadAppPlugIn = C;
Hquery.downloadAppPlugInOpenApp = function(L) {
var M = F(L);
openApp(M);
}
});

最新文章

  1. Linux基础介绍【第六篇】
  2. mac下生成ssh keys 并上传github仓储
  3. Netbackup磁带过期处理
  4. cocos2d-x-3.1 经常使用宏 (coco2d-x 学习笔记五)
  5. Android原生代码与html5交互
  6. mxgraph进阶(四)mxGraph再启程
  7. URL存在跨站漏洞http host头攻击漏洞解决方案
  8. webstorm设置VCS:版本控制顶部按钮
  9. 06 自学Aruba之win7系统802.1x认证网卡设置指导
  10. JAVA编程思想学习笔记7-chap19-21-斗之气7段
  11. JDK版本的特性
  12. Idea设置默认不折叠一行的函数
  13. GoLang 命令
  14. 寻路DEMO
  15. 超全面的JavaWeb笔记day12&lt;Jsp&amp;JavaBean&amp;El表达式&gt;
  16. Resin任意文件读取漏洞
  17. php 快速读取文件夹下文件列表
  18. Unit02: 参数值注入 、 基于注解的组件扫描
  19. ui-router 留存
  20. 复制新增树状数据_ParentID也需要更新

热门文章

  1. html中空格字符实体整理
  2. 基本数据类型对象包装(Integer等)
  3. 20145215《网络对抗》Exp8 Web基础
  4. .net视频教程代码之《提交注册内容》
  5. CentOS6.x下源码安装MySQL5.5
  6. docker部署安装
  7. Java NIO 机制分析(一) Java IO的演进
  8. elementUI 表格设置表头样式
  9. Visual Studio 各版本下载
  10. MyBatis联合查询和使用association 进行分步式查询