• 又到周末了,我们一起来研究【浏览器如何检测是否安装app】吧


    前言

    扯淡

    这个月比较倒霉,我送了女朋友一台笔记本电脑作为生日礼物,结果15天一过电脑就坏了,悲剧的我还把电脑盒子给扔了!淘宝不给换更不给退

    于是被女朋友臭骂了一过星期后,今天本来在公司有任务的,但是去修了个电脑(换主板啊......),一蹉跎就快五点了,现在反正干劲也不行,就写篇博客吧

    需求

    上周五的时候,确切说是周四晚上,老板终于又递上了一个神奇的需求

    浏览器检测手机是否安装app

    尼玛,反正在我看来,这个需求够奇葩的,当时我还一致认为不能完成,但是最后也居然想出了(抄出了)一个办法,于是这里拿出来与各位分享下

    在此之前,我们继续聊下上次遇到的tap点透问题

    tap“点透”再探索

    http://www.cnblogs.com/yexiaochai/p/3377900.html

    http://www.cnblogs.com/yexiaochai/p/3391015.html

    看过上面两篇博客的的朋友应该知道我们为什么要使用tap事件替换click事件,然后大概知道tap会带来哪些问题,以及我是如何解决这些问题的

    虽然完整解决方案因为公司财产问题未拿出来,但是基本思路是有了,其核心就是蒙版遮盖!

    话说还头,这个蒙版其实还是不太能让人接受,这不我又请教了我一个同事,我们同事提出了一个属性:

    pointer-events属性值详解

    • auto——效果和没有定义pointer-events属性相同,鼠标不会穿透当前层。在SVG中,该值和visiblePainted的效果相同。
    • none——元素不再是鼠标事件的目标,鼠标不再监听当前层而去监听下面的层中的元素。但是如果它的子元素设置了pointer-events为其它值,比如auto,鼠标还是会监听这个子元素的。
    • 其它属性值为SVG专用,这里不再多介绍了。

    这个属性,通过前端观察/和张鑫旭的博客再深入了解一番过后发现,这个家伙可以消除一个元素的鼠标事件呢!!!自然也包括touchstart了,于是老夫感兴趣了,便有了今天这个插曲

    是否继承

    我们首先来看看这个属性是否会被继承:

    http://sandbox.runjs.cn/show/teegz43u

     1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     2 <html xmlns="http://www.w3.org/1999/xhtml">
     3 <head>
     4     <title></title>
     5     <meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
     6     <meta content="telephone=no" name="format-detection" />
     7     <meta name="apple-mobile-web-app-capable" content="yes" />
     8     <style>
     9         div { display: block; border: 1px solid black;  margin: 10px; padding: 10px; }
    10     </style>
    11     <script id="others_zepto_10rc1" type="text/javascript" class="library" src="/js/sandbox/other/zepto.min.js"></script>
    12     
    13 </head>
    14 <body>
    15 
    16     <div id="p1">
    17         p1
    18         <div id="p1-1">
    19             p1-1
    20             <div id="p1-1-1">
    21                 p1-1-1
    22             </div>
    23              <div id="p1-1-2">
    24                 p1-1-2
    25             </div>
    26         </div>
    27     </div>
    28 
    29      <div id="p2">
    30         p2
    31         <div id="p2-1">
    32             2-1
    33             <div id="p2-1-1">
    34                 p2-1-1
    35             </div>
    36              <div id="p2-1-2">
    37                 p2-1-2
    38             </div>
    39         </div>
    40     </div>
    41 
    42 </body>
    43 <script type="text/javascript">
    44     $('div').click(function () {
    45         alert($(this).attr('id'))
    46 
    47     })
    48 </script>
    49 </html>

    首先,现在鼠标点击会有一个冒泡的过程,所以会一次弹出提示框,现在我们将下面的p2的style加上我们的pointer-events属性试试点击是否有效果

    结果表明,设置了pointer-events: none; 后,该元素以及下面的元素的click事件全部没有了

    甚至是我们的input框都不会获取焦点了!!!,所以这个家伙确实够厉害,但是不会取消事件冒泡

    有了这个结论,我们上我们的重量级代码吧,这个代码请各位用手机测试

    属性解决点透

     1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     2 <html xmlns="http://www.w3.org/1999/xhtml">
     3 <head>
     4     <title></title>
     5     <meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
     6     <meta content="telephone=no" name="format-detection" />
     7     <meta name="apple-mobile-web-app-capable" content="yes" />
     8     <style>
     9         #list { display: block; position: absolute; top: 100px; left: 10px; width: 200px; height: 100px; }
    10         div { display: block; border: 1px solid black; height: 500px; width: 100%; }
    11         #input { width: 80px; height: 200px; display: block; }
    12     </style>
    13     <script id="others_zepto_10rc1" type="text/javascript" class="library" src="/js/sandbox/other/zepto.min.js"></script>
    14 </head>
    15 <body>
    16     <div id="list" style="background: gray;">
    17     </div>
    18     <div id="wrapper">
    19         <div id="d">
    20             <input type="text" id="input" />
    21         </div>
    22     </div>
    23 </body>
    24 <script type="text/javascript">
    25     var list = $('#list');
    26     var d = $('#d');
    27     var input = $('#input');
    28     input.tap(function (e) {
    29         input.val(new Date().getTime());
    30     });
    31     list.tap(function (e) {
    32         //        $('input').css("pointer-events", "none");
    33         list.hide();
    34         setTimeout(function () {
    35             list.show();
    36             //            $('input').css("pointer-events", "auto");
    37         }, 1000);
    38     });
    39     d.tap(function () {
    40         d.append($('<p>div tap</p>'));
    41     });
    42     
    43 </script>
    44 </html>

    http://sandbox.runjs.cn/show/wub3i7fr

    这里各位请使用手机访问试试,现在这个网页有几个问题:

    我点击灰色区域会将灰色区域隐藏,灰色区域消失,一秒后重现,于是可能发生两个问题:

    ① 某些浏览器中后面的div tap事件会触发

    ② input元素必定获得焦点

    div事件有些时候我们可以通过阻止冒泡处理,但是input这个问题基本不可调和,因为其获得焦点弹出键盘十分恼火

    元素我们是通过一个蒙版解决,先我们来看看是否可以给我们的容器wrapper加上一个css属性解决呢???

     1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     2 <html xmlns="http://www.w3.org/1999/xhtml">
     3 <head>
     4     <title></title>
     5     <meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
     6     <meta content="telephone=no" name="format-detection" />
     7     <meta name="apple-mobile-web-app-capable" content="yes" />
     8     <style>
     9         #list { display: block; position: absolute; top: 100px; left: 10px; width: 200px; height: 100px; }
    10         div { display: block; border: 1px solid black; height: 500px; width: 100%; }
    11         #input { width: 80px; height: 200px; display: block; }
    12     </style>
    13     <script id="others_zepto_10rc1" type="text/javascript" class="library" src="/js/sandbox/other/zepto.min.js"></script>
    14 </head>
    15 <body>
    16     <div id="list" style="background: gray;">
    17     </div>
    18     <div id="wrapper">
    19         <div id="d">
    20             <input type="text" id="input" />
    21         </div>
    22     </div>
    23 </body>
    24 <script type="text/javascript">
    25     var list = $('#list');
    26     var d = $('#d');
    27     var input = $('#input');
    28     input.tap(function (e) {
    29         input.val(new Date().getTime());
    30     });
    31     list.tap(function (e) {
    32         $('#wrapper').css("pointer-events", "none");
    33         list.hide();
    34         setTimeout(function () {
    35             $('#wrapper').css("pointer-events", "auto");
    36         }, 350)
    37         setTimeout(function () {
    38             list.show();
    39         }, 1000);
    40     });
    41     d.tap(function () {
    42         d.append($('<p>div tap</p>'));
    43     });
    44     
    45 </script>
    46 </html>

    http://sandbox.runjs.cn/show/1wldtigt

    可以看到,我们解决了点透的问题,所以有我有这些厉害的同事是很幸运的,有了这个方案,我们就可以在zepto中封装我们的代码了

    在tap点击后为容器标签设置该属性,350ms后取消即可,这样可以最大程度的包装代码不会修改

    但是这个方案不是没有问题:

    最重要的是他依然有个时间阀值,经过我测试时350ms,意思是我使用tap事件后会有350ms的事件某些区域完全无法点击

    那么容器所占区域小的话还可接受,如果所占区域大的话就是噩梦,因为用户的点击明显会出现阻力

    然后,毕竟会点透的情况不是多数,所以此方案仍有缺陷,最后还是得动一些其它力气

    后续

    这次tap的研究先到这里,我们我们有机会再继续,所以回到我们今天的主题吧!!!

    浏览器检测手机是否安装app

    这个需求初次提出其实让人感觉很为难,至少我是很为难的,因为压根就找不到办法嘛,经过周四晚上的纠结,基本就放弃了

    第二天也给老大说搞不定,老大基本也仍为搞不定,但是这个需求是最大的老大提出的,所以跟进力度很强,这不是,过了没多久就来了个vip(代表级别高......)

    哥来了就寄出了法宝,先是一个国外的网站,然后就是我们传说中的淘宝了

    PS:说实话,虽然电脑的事情与淘宝无关,但是老夫现在对淘宝还是比较怨念的!!!!

    淘宝不愧是业内技术领先的技术团队,我们来看看他的网站:

    其它不必关注,我们就看这个“立即打开”!!!各位知道手机上这个立即打开干了什么吗?

    这个家伙不得了,如果按照了app 的话点击立即打开就会打开app,如果没有按照的话居然跳向了市场连接

    在某些时候这个对等与他有一个a标签会根据需求而获得不同的值!!!

    但是,我们知道打开app是安装了app才会打开的,不然就是个死链接,死链接必然打不开!于是带着好奇带着敬畏,我们打开了淘宝的js库

    PS:淘宝压缩混淆后js确实很小,而且没有使用类库哦

    各位看官直接找到这个目录吧,于是进去我们一步步跟进去:

    ① 点击点

    虽然小生本领不行,但是读代码还是入门的,所以国内一旦出了什么心技术,基本很快就能普及,这就是国内的技术,不是做不出来,就是不知道做出了是什么样子

    一旦你做出了,那么我也能做出了,并且做的更好,所以我们缺乏创新啊......

    我们找到了入口,于是进入install方法

    ② install

    这群代码一目了然,读到这里,其实可以很轻易的猜测实现方案了!

    ③ 猜测实现方案

    于是我就开始猜测,猜测的结果就是:

    如果安装app 的情况下,打开链接会让window失去焦点,于是清除了计时器
    如果没有安装app计时器里面的代码会执行,所以跳向了app市场

    当然,最后发现一个问题:手机上网页无法失去焦点,这只是我自己的判断(无法失去焦点),所以最后也放弃了这个猜测

    ④ 陷入僵局

    于是思路再次陷入僵局,任务不能实现,但是将淘宝代码搞下来,也无法实现,最后就开始以各种漫无目的,垃圾的办法搞,终于不注意成功了一次!!!

    无意义的成功是因为将定时器设置的很大......

    ⑤ 解决方案

    最后发现了方案,安装app 的情况下,网页会进入后台打开app!!!

    网页进入后台后会挂起js 的执行,但是这个期间有600-1000ms的时间js仍然会执行

    淘宝执行的阀值是600,我们大概是900,所以一直在原地踏步了很久

    这个网页进入后台却成了解决问题的关键,于是新鲜代码出来了:

     1 var log = function (msg) {
     2     $('body').before('<div class="log">' + msg + '</div>');
     3 };
     4 var timeout, t = 1000, hasApp = true;
     5 setTimeout(function () {
     6     if (hasApp) {
     7         log('安装了app');
     8         $('#dl_app').hide();
     9 
    10     } else {
    11         log('未安装app');
    12         $('#dl_app').show();
    13         log('开始强制下载');
    14         forceDownload();
    15     }
    16 }, 2000)
    17 function testApp() {
    18     var t1 = Date.now();
    19     var ifr = $('<iframe id="ifr"></iframe>')
    20     ifr.attr('src', '您们app的协议');
    21     $('body').append(ifr);
    22     timeout = setTimeout(function () {
    23         try_to_open_app(t1);
    24     }, t);
    25 }
    26 function try_to_open_app(t1) {
    27     var t2 = Date.now();
    28     if (!t1 || t2 - t1 < t + 200) {
    29         hasApp = false;
    30     }
    31 }
    32 testApp();

    将这段代码加入网站首页1-2秒后hasApp就会告诉我们是否安装了app,当然问题也很明显:

    缺陷

    ① 经测试,如果未安装app的情况下,safari会给出一个alert类似的提示,老夫将它去不掉!!!

    PS:如果各位知道怎么去掉,请赐教

    ② 进入H5站点,如果安装了app便会打开app,这个是无法避免的

    除了上面两个较明显的缺陷,其它还好了......

    结语

    我们今天的学习暂时到此,也不知道对各位有没有用

  • 相关阅读:
    Linux添加系统环境变量
    keras 或 tensorflow 调用GPU报错:Blas GEMM launch failed
    python 安装虚拟环境
    Seq2Seq 到 Attention的演变
    聊天内容处理笔记
    LSTM 详解
    keras 打印模型图
    zip 的对象是不能用索引去取的
    c# 反射获取属性值 TypeUtils
    .iml文件恢复
  • 原文地址:https://www.cnblogs.com/yexiaochai/p/3439179.html
Copyright © 2020-2023  润新知