zoukankan      html  css  js  c++  java
  • 京东在html5页面中打开本地app的解决方案

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

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

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

      1 (function(){
      2     // 判断浏览器
      3             var Navigator = navigator.userAgent;
      4         var ifChrome = Navigator.match(/Chrome/i) != null && Navigator.match(/Version/d+.d+(.d+)?sChrome//i) == null ? true : false;  
      5         var ifAndroid = (Navigator.match(/(Android);?[s/]+([d.]+)?/)) ? true : false;
      6         var ifiPad = (Navigator.match(/(iPad).*OSs([d_]+)/)) ? true : false;
      7         var ifiPhone = (!ifiPad && Navigator.match(/(iPhonesOS)s([d_]+)/)) ? true : false;
      8         var ifSafari = (ifiPhone || ifiPad) && Navigator.match(/Safari/);
      9         var version = 0;
     10         ifSafari && (version = Navigator.match(/Version/([d.]+)/));
     11 
     12             version = parseFloat(version[1], 10);
     13             // 是否从微信打开
     14         var ifWeixin = navigator.userAgent.indexOf("MicroMessenger") >= 0; // weixin
     15         var j = false;
     16         var iframe = "plugIn_downloadAppPlugIn_loadIframe";
     17         var t = false;
     18         var i = 0;
     19         var B = {};
     20         var b = {};
     21         var selector = null;
     22         var Hquery = {};
     23             // 判断当前使用的js框架是zepto还是jquery
     24         var Query = window.Zepto || window.jQuery ? true : false;
     25         var g = [];
     26             // 是否存在html5的localStorage 存储
     27         var v = window.localStorage ? true : false;
     28         var o = "mdownloadAppPlugInskip";
     29         var p = null;
     30 
     31         function m() { // 打印时间 例如:2016-5-18
     32             var M = new Date();
     33             var N = M.getFullYear();
     34             var O = M.getMonth() + 1;
     35             var L = M.getDate();
     36             strDate = N + "-" + O + "-" + L;
     37             return strDate
     38         }
     39             // 微信相关操作
     40         function r() { // weixin api
     41             WeixinJSBridge.invoke("getInstallState", {
     42                 packageName: "com.jingdong.app.mall",
     43                 packageUrl: "openApp.jdMobile://"
     44             }, function(M) {
     45                 var N = M.err_msg,
     46                     L = 0;
     47                 if (N.indexOf("get_install_state:yes") > -1) {
     48                     j = true
     49                 }
     50             })
     51         }
     52            // 根据是否存在js框架进行dom和时间的绑定
     53         function bind(dom, event, fun) { // bind event
     54             if (Query) {
     55                 selector("#" + dom).bind(event, fun)
     56             } else {
     57                 selector("#" + dom).addEventListener(event, fun, !1)
     58             }
     59         }
     60 
     61         function z(L) {
     62             var M = (L || "mGen") + (++i);
     63             return M
     64         }
     65             // 微信操作
     66         if (ifWeixin) { // if navigitor is weixin 
     67             if (window.WeixinJSBridge && WeixinJSBridge.invoke) {
     68                 r()
     69             } else {
     70                 document.addEventListener("WeixinJSBridgeReady", r, !1)
     71             }
     72         }
     73 
     74             // 如果存在js框架
     75         if (Query) {
     76             selector = window.$;
     77             Hquery = window.$
     78         } else {
     79             selector = function(obj) {
     80                 if (typeof obj == "object") {
     81                     return obj
     82                 }
     83                 return document.querySelector(obj);
     84             };
     85             if (!window.$) {
     86                 window.$ = Hquery = selector
     87             } else {
     88                 Hquery = window.$ 
     89             }
     90         }
     91         window.onblur = function() {
     92             for (var L = 0; L < g.length; L++) {
     93                 clearTimeout(g[L])
     94             }
     95         };
     96              // 设置cookie。
     97         function e(N) {
     98             var M = document.cookie.indexOf(N + "=");
     99             if (M == -1) {
    100                 return ""
    101             }
    102             M = M + N.length + 1;
    103             var L = document.cookie.indexOf(";", M);
    104             if (L == -1) {
    105                 L = document.cookie.length
    106             }
    107             return document.cookie.substring(M, L)
    108         }
    109             // 设置cookie
    110         function l(N, P, L, Q, O) { 
    111             var R = N + "=" + escape(P);
    112             if (L != "") {
    113                 var M = new Date();
    114                 M.setTime(M.getTime() + L * 24 * 3600 * 1000);
    115                 R += ";expires=" + M.toGMTString()
    116             }
    117             if (Q != "") {
    118                 R += ";path=" + Q
    119             }
    120             if (O != "") {
    121                 R += ";domain=" + O
    122             }
    123             document.cookie = R
    124         }
    125 
    126             // 打开的链接集合
    127         function F(L) {
    128             var url = {
    129                 downAppURl: "http://h5.m.jd.com/active/download/download.html?channel=jd-m",
    130                 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",
    131                 downWeixin: "http://a.app.qq.com/o/simple.jsp?pkgname=com.jingdong.app.mall&g_f=991850",
    132                 downIpad: "https://itunes.apple.com/cn/app/jing-dong-hd/id434374726?mt=8",
    133                 inteneUrl: "openApp.jdMobile://360buy?type=1",
    134                 inteneUrlParams: null,
    135                 openAppBtnId: "",
    136                 closePanelBtnId: "",
    137                 closePanelId: "",
    138                 closeCallblack: null,
    139                 closeCallblackSource: null,
    140                 cookieFlag: null,
    141                 noRecord: false,
    142                 sourceType: "JSHOP_SOURCE_TYPE",
    143                 sourceValue: "JSHOP_SOURCE_VALUE",
    144                 openAppEventId: "MDownLoadFloat_OpenNow",
    145                 closePanelEventId: "MDownLoadFloat_Close"
    146             };
    147             if (L) {
    148                 for (var M in L) {
    149                     if (M && L[M]) {
    150                         url[M] = L[M]
    151                     }
    152                 }
    153             }
    154             return url
    155         }
    156             // 敲黑板 重点内容。看京东是怎么解决兼容问题的。
    157         function openApp(N, L) { // openApp
    158             var R = h(N); //获取相对应的url
    159             var O = null;
    160             if (ifWeixin) { // 如果是微信端
    161                 var M = null;
    162                 if (j) {
    163                     M = R
    164                 } else {
    165                     M = N.downWeixin
    166                 }
    167                 location.href = M; // 直接使用location.href打开
    168                 return
    169             }
    170             if (ifiPad) { // 如果是ipad
    171                 O = N.downIpad
    172             } else { 
    173                 if (ifiPhone) { // 如果是iphone
    174                     O = N.downAppIos
    175                 } else {
    176                     O = N.downAppURl
    177                 }
    178             }
    179 
    180             if (ifChrome) { // 如果是chrome
    181                 if (ifAndroid) { //安卓浏览器
    182                     var Q = R;
    183                     R = y(Q);
    184                                     // 延后50毫秒
    185                     setTimeout(function() {
    186                         window.location.href = R 
    187                     }, 50)
    188                 }
    189             }
    190             if (ifSafari && version >= 9) { // 判断safari版本 如果大于9
    191                 setTimeout(function() {  // 必须要使用settimeout
    192                     var S = document.createElement("a"); //创建a元素
    193                     S.setAttribute("href", R), S.style.display = "none", document.body.appendChild(S);
    194                     var T = document.createEvent("HTMLEvents"); // 返回新创建的 Event 对象,具有指定的类型。
    195                     T.initEvent("click", !1, !1)// 初始化新事件对象的属性,   S.dispatchEvent(T)  // 绑定事件
    196                 }, 0)
    197             } else {
    198                 document.querySelector("#" + iframe).src = R // 将iframe增加src
    199             }
    200             var P = Date.now();
    201             setTimeout(function() {
    202                 if (L) {
    203                     var S = setTimeout(function() {
    204                         x(P, O)
    205                     }, 1500);
    206                     g.push(S)
    207                 }
    208             }, 100)
    209         }
    210             // x方法
    211         function x(N, downUrl) {
    212             var L = Date.now();
    213             if (N && (L - N) < (1500 + 200)) {
    214                 window.location.href = downUrl
    215             }
    216         }
    217 
    218         function h(N) {
    219             var V = [];
    220             var P = N.inteneUrlParams;
    221             var T = {
    222                 category: "jump",
    223                 des: "productDetail"
    224             };
    225             if (N.sourceType && N.sourceValue) {
    226                 T.sourceType = N.sourceType;
    227                 T.sourceValue = N.sourceValue;
    228                 if (P && !P.sourceType && !P.sourceValue) {
    229                     P.sourceType = N.sourceType;
    230                     P.sourceValue = N.sourceValue
    231                 }
    232             }
    233             if (P) {
    234                 for (var U in P) {
    235                     if (U && P[U]) {
    236                         V.push('"' + U + '":"' + P[U] + '"')
    237                     }
    238                 }
    239             } else {
    240                 for (var U in T) {
    241                     if (U && T[U]) {
    242                         V.push('"' + U + '":"' + T[U] + '"')
    243                     }
    244                 }
    245             }
    246             try {
    247                 var Q = MPing.EventSeries.getSeries();
    248                 if (Q) {
    249                     var W = JSON.parse(Q);
    250                     W.jdv = encodeURIComponent(e("__jdv"));
    251                     W.unpl = encodeURIComponent(e("unpl"));
    252                     W.mt_xid = encodeURIComponent(e("mt_xid"));
    253                     W.mt_subsite = encodeURIComponent(e("mt_subsite"))
    254                 }
    255                 var S = {
    256                     mt_subsite: encodeURIComponent(e("mt_subsite")),
    257                     __jdv: encodeURIComponent(e("__jdv")),
    258                     unpl: encodeURIComponent(e("unpl")),
    259                     __jda: encodeURIComponent(e("__jda"))
    260                 };
    261                 Q = JSON.stringify(W);
    262                 V.push('"m_param":' + Q);
    263                 V.push('"SE":' + JSON.stringify(S))
    264             } catch (R) {
    265                 V.push('"m_param":null')
    266             }
    267             var M = "{" + V.join(",") + "}";
    268             var O = N.inteneUrl.split("?");
    269             var L = null;
    270             if (O.length == 2) {
    271                 L = O[0] + "?" + O[1] + "&params=" + M
    272             } else {
    273                 L = O[0] + "?params=" + M
    274             }
    275             return L
    276         }
    277 
    278         function y(L) {
    279             return "intent://m.jd.com/#Intent;scheme=" + L + ";package=com.jingdong.app.mall;end"
    280         }
    281 
    282         function n(L) {
    283             if (L.openAppBtnId) {
    284                 B[L.openAppBtnId] = L;
    285                 G(L.openAppBtnId, L.openAppEventId);
    286                 bind(L.openAppBtnId, "click", function() {
    287                     var P = this.getAttribute("id");
    288                     var M = B[P];
    289                     if (!t) {
    290                         var N = document.createElement("iframe");
    291                         N.id = iframe;
    292                         document.body.appendChild(N);
    293                         document.getElementById(iframe).style.display = "none";
    294                         document.getElementById(iframe).style.width = "0px";
    295                         document.getElementById(iframe).style.height = "0px";
    296                         t = true
    297                     }
    298                     var O = M.cookieFlag ? "downloadAppPlugIn_downCloseDate_" + M.cookieFlag : "downloadAppPlugIn_downCloseDate";
    299                     l(O, Date.now() + "_2592000000", 60, "/", "m.jd.com");
    300                     l(O, Date.now() + "_2592000000", 60, "/", "m.jd.hk");
    301                     openApp(M, true)
    302                 })
    303             }
    304         }
    305 
    306         function D(M) {
    307             if (M.closePanelBtnId && M.closePanelId) {
    308                 B[M.closePanelBtnId] = M;
    309                 G(M.closePanelBtnId, M.closePanelEventId);
    310                 var Q = M.cookieFlag ? "downloadAppPlugIn_downCloseDate_" + M.cookieFlag : "downloadAppPlugIn_downCloseDate";
    311                 var O = e(Q);
    312                 var P = null;
    313                 if (O) {
    314                     P = O.split("_");
    315                     if (P.length == 2) {
    316                         P[0] = parseInt(P[0], 10);
    317                         P[1] = parseInt(P[1], 10)
    318                     } else {
    319                         P = null
    320                     }
    321                 }
    322                 var L = Date.now();
    323                 if (Html5Plus() || (!M.noRecord && P && P.length == 2 && (L - P[0]) < P[1])) {
    324                     document.querySelector("#" + M.closePanelId).style.display = "none";
    325                     if (M.closeCallblack) {
    326                         var N = M.closeCallblackSource ? M.closeCallblackSource : null;
    327                         M.closeCallblack.call(N)
    328                     }
    329                     return
    330                 } else {
    331                     document.querySelector("#" + M.closePanelId).style.display = "block"
    332                 }
    333                 bind(M.closePanelBtnId, "click", function() {
    334                     var U = this.getAttribute("id");
    335                     var R = B[U];
    336                     var T = R.cookieFlag ? "downloadAppPlugIn_downCloseDate_" + R.cookieFlag : "downloadAppPlugIn_downCloseDate";
    337                     if (!R.noRecord) {
    338                         l(T, Date.now() + "_259200000", 60, "/", "m.jd.com");
    339                         l(T, Date.now() + "_259200000", 60, "/", "m.jd.hk")
    340                     }
    341                     document.querySelector("#" + R.closePanelId).style.display = "none";
    342                     if (R.closeCallblack) {
    343                         var S = R.closeCallblackSource ? R.closeCallblackSource : null;
    344                         R.closeCallblack.call(S)
    345                     }
    346                 })
    347             }
    348         }
    349 
    350         function Html5Plus() { // htmlplus
    351             if (Navigator.indexOf("Html5Plus") >= 0) {
    352                 return true
    353             } else {
    354                 return false
    355             }
    356         }
    357 
    358         function G(P, M) {
    359             try {
    360                 var O = document.getElementById(P);
    361                 var L = O.className;
    362                 if (L) {
    363                     L = L + " J_ping"
    364                 } else {
    365                     L = "J_ping"
    366                 }
    367                 O.className = L;
    368                 O.setAttribute("report-eventid", M)
    369             } catch (N) {}
    370         }
    371 
    372         function C(L) {
    373             var M = F(L);
    374             n(M);
    375             D(M)
    376         }
    377         Hquery.downloadAppPlugIn = C;
    378         Hquery.downloadAppPlugInOpenApp = function(L) {
    379             var M = F(L);
    380             openApp(M);
    381         }
    382     });
  • 相关阅读:
    结合<span id="outer"><span id="inter">text</span></span>这段结构,谈谈innerHTML、outerHTML、innerText之间的区别
    字符串的方法slice、substr、substring对比
    为什么两个一样的对象,用===打印是false
    this指向
    复制对象的方法
    Promise以及async和await的用法
    前端性能优化&&网站性能优化
    P1510 精卫填海
    分解质因数
    P2648 赚钱
  • 原文地址:https://www.cnblogs.com/zhaobao1830/p/9041060.html
Copyright © 2011-2022 走看看