这个月比较倒霉,我送了女友一台笔记本电脑做为生日礼物,结果15天一过电脑就坏了,悲剧的我还把电脑盒子给扔了!淘宝不给换更不给退javascript
因而被女友臭骂了一过星期后,今天原本在公司有任务的,可是去修了个电脑(换主板啊......),一蹉跎就快五点了,如今反正干劲也不行,就写篇博客吧css
上周五的时候,确切说是周四晚上,老板终于又递上了一个神奇的需求html
浏览器检测手机是否安装app
尼玛,反正在我看来,这个需求够奇葩的,当时我还一致认为不能完成,可是最后也竟然想出了(抄出了)一个办法,因而这里拿出来与各位分享下前端
在此以前,咱们继续聊下上次遇到的tap点透问题java
http://www.cnblogs.com/yexiaochai/p/3377900.htmlweb
http://www.cnblogs.com/yexiaochai/p/3391015.html浏览器
看过上面两篇博客的的朋友应该知道咱们为何要使用tap事件替换click事件,而后大概知道tap会带来哪些问题,以及我是如何解决这些问题的app
虽然完整解决方案由于公司财产问题未拿出来,可是基本思路是有了,其核心就是蒙版遮盖!ide
话说还头,这个蒙版其实仍是不太能让人接受,这不我又请教了我一个同事,咱们同事提出了一个属性:学习
这个属性,经过前端观察/和张鑫旭的博客再深刻了解一番事后发现,这个家伙能够消除一个元素的鼠标事件呢!!!天然也包括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的研究先到这里,咱们咱们有机会再继续,因此回到咱们今天的主题吧!!!
这个需求初次提出其实让人感受很为难,至少我是很为难的,由于压根就找不到办法嘛,通过周四晚上的纠结,基本就放弃了
次日也给老大说搞不定,老大基本也仍为搞不定,可是这个需求是最大的老大提出的,因此跟进力度很强,这不是,过了没多久就来了个vip(表明级别高......)
哥来了就寄出了法宝,先是一个国外的网站,而后就是咱们传说中的淘宝了
PS:说实话,虽然电脑的事情与淘宝无关,可是老夫如今对淘宝仍是比较怨念的!!!!
淘宝不愧是业内技术领先的技术团队,咱们来看看他的网站:
其它没必要关注,咱们就看这个“当即打开”!!!各位知道手机上这个当即打开干了什么吗?
这个家伙不得了,若是按照了app 的话点击当即打开就会打开app,若是没有按照的话竟然跳向了市场链接
在某些时候这个对等与他有一个a标签会根据需求而得到不一样的值!!!
可是,咱们知道打开app是安装了app才会打开的,否则就是个死连接,死连接必然打不开!因而带着好奇带着敬畏,咱们打开了淘宝的js库
PS:淘宝压缩混淆后js确实很小,并且没有使用类库哦
各位看官直接找到这个目录吧,因而进去咱们一步步跟进去:
虽然小生本领不行,可是读代码仍是入门的,因此国内一旦出了什么心技术,基本很快就能普及,这就是国内的技术,不是作不出来,就是不知道作出了是什么样子
一旦你作出了,那么我也能作出了,而且作的更好,因此咱们缺少创新啊......
咱们找到了入口,因而进入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,这个是没法避免的
除了上面两个较明显的缺陷,其它还好了......
咱们今天的学习暂时到此,也不知道对各位有没有用