浅谈项目中遇到的关于移动web的JS坑
来源:互联网 发布:淘宝网生产许可证编号 编辑:程序博客网 时间:2024/06/05 13:27
因为项目需要,自己设计并构建了很多手机web的页面,现在就让我来吐槽一下其中遇到的坑,与君共勉。
1.手机横竖屏检测事件
window.addEventListener('orientationchange', function(event){ if ( window.orientation == 180 || window.orientation==0 ) { alert("竖屏"); } if( window.orientation == 90 || window.orientation == -90 ) { alert("横屏"); } });
这个事件是我们遇到手机横屏问题的时候经常会想到的事件,但是在使用的过程中,发现这个事件响应在IOS和android兼容不是很好,10次总要失败个2-3次,这简直要逼死强迫症啊,后来我发现有另一个事件能够完美的处理横竖屏转换,而且百试百灵。就是浏览器尺寸变化响应事件。
window.onresize = function(){ resizeS();//检测到窗口改变所做的对应操作(比如重新计算高度之类的,因为这个时候高度已经变为改变后的高度,而不是原来的高度了)。 }
在使用这个事件的时候要注意的一点就是:谷歌浏览器中window.onresize 事件默认会执行两次(偶尔也会只执行一次,网上大部分说法认为这是Chrome的bug)。
所以为了避免产生这样的情况:一般来说推荐新建一个标志位 延时复位控制它不让它自己执行第二次。
var firstOnResizeFire = true;//谷歌浏览器onresize事件会执行2次,这里加个标志位控制 window.onresize = function() { if (firstOnResizeFire) { resizeS(); //0.5秒之后将标志位重置(Chrome的window.onresize默认执行两次) setTimeout(function() { firstOnResizeFire = true; }, 500); }
这里我顺便贴出我对窗口尺寸改变之后所做的页面调整代码(这段代码我是用在我之前文章写的固定导航里的),仅供参考
function resizeS(){ $(".container").height(document.body.clientHeight-$("#nav").height());//让页面内容完全显示,而不会因为固定导航栏的原因内容被挤到屏幕之外 $(".screen_content").height(document.body.clientHeight-$("#nav").height()); if(!$(".dd").is(".hide")){ $(".dd").css("height","auto"); if($(".dd").height() > $(".container").height()){ $(".dd").height($(".container").height()); } } $(".subitems").each( function(){if(!$(this).is(".hide")){ $(this).css("height","auto"); if($(this).height() > $(".container").height()){ $(this).height($(".container").height()); } } }); if(!$(".drd").is(".hide")){ $(".drd").css("height","auto"); if($(".drd").height() > $(".container").height()){ $(".drd").height($(".container").height()); } } }
2.用jquery获取元素高度出现height=0px或-1的情况,然后你在调试页面发现,其实元素是有高度的,这个时候是不是很摸不着头脑,我当时也调试了半天,最后发现,原来是这个元素的父元素hide了(问题在于父元素hide了子元素还在显示,这就尴尬了)。既然hide了当然是获取不到高度的,这个就涉及到移动端用mouseover/mouseout事件代替PC的hover事件产生的问题了。我们都知道手机都是触屏而不是鼠标,而hover事件在移动端的效果相当于click事件,但是如果使用mouseover/mouseout事件,触摸的时候这两个事件代码都被执行,然后mouseout事件里写的hide代码就被执行了。所以,后来我就只使用了mouseover事件就好了。其实我觉得吧,直接用click事件就挺好,也别整什么幺蛾子了。我就是想的太多,总觉得手机页面也会在PC上看,hover效果好。不过事实是,手机页面在PC上看,无关JS也很丑。
3.页面禁止滚动的问题。这个问题算是我最纠结的了。先上代码再解释
$('#bg').bind("touchmove",function(e){ e.preventDefault(); //禁止遮罩层滚动。 }); //禁止滑动 function stop(){ $('.dd-inner').parents().each(function(){ if($(this).tagName!='HTML' && $(this).tagName!='BODY'){ $(this).attr('overflow-back',this.style.overflow); this.style.overflow='hidden'; } //this.addEventListener("touchmove",mo,false); }); document.body.style.overflow='hidden'; document.addEventListener("touchmove",mo,false); } //取消滑动限制 function move(){ $('.dd-inner').parents().each(function(){ if($(this).tagName!='HTML' && $(this).tagName!='BODY'){ this.style.overflow=$(this).attr('overflow-back'); } //this.removeEventListener("touchmove",mo,false); }); document.body.style.overflow='';//出现滚动条 document.removeEventListener("touchmove",mo,false); } $('.dd').bind('touchmove',function(e){e.preventDefault(); });//禁止滚动事件冒泡到父类,使得自己可以滚动,父类禁止滚动 var height = function(){return Math.floor(document.body.clientHeight-$("#nav").height() - $(".void").height())}; $('.dd-inner').bind('touchmove',function(e){e.stopPropagation(); });//禁止滚动事件冒泡到父类,使得自己可以滚动,父类禁止滚动 $('html,body').animate({scrollTop: '0px'}, 100);//因为页面很长,有纵向滚动条,先让页面滚动到最顶端,然后禁止滑动事件,这样可以使遮罩层锁住整个屏幕
是不是觉得写得很全了。禁止了手指滑动的滚动和鼠标滚轮滚动了吧。但是实际上出来的效果是要么是所有内容都不能滚,包括我本来想要开放滚动事件的子类。要么是能滚动的子类一旦出现,滑动这个可滚动的子类到底部之后继续滑动,你会发现整个文档都跟着一块移动了(文档内容超过一屏的时候)。跟我想要的效果相差很大。后来我试过比较好的解决这个问题的方法是,在所有可滚动的子类响应事件中加上
$(“.dd-inner”)[0].style.overflow=’scroll’;//dd-inner是可滚动的子类的直接父类
才算解决这个问题。代码示例如下(上面写的禁止文档滚动事件代码就不再重复了,同样该代码也是我之前做固定导航使用的代码:
$("#nav").mouseover(function(e) { if($(".dd").is(".hide")){ stop(); $(".dd").removeClass("hide"); if($(".dd-inner").height() > height()){ $(".dd-inner").height(height()); } $(".dd-inner")[0].style.overflow='scroll'; } $('html,body').animate({scrollTop: '0px'}, 100);//因为页面很长,有纵向滚动条,先让页面滚动到最顶端,然后禁止滑动事件,这样可以使遮罩层锁住整个屏幕 }); $('.yiji').on('click', function(e){ e.stopPropagation(); }); $(".yiji").hover(function(e){//二级导航 if($(this).next(".subitems").is(".hide")){ $(this).next(".subitems").removeClass("hide"); $(this).addClass("hover").siblings(".yiji").removeClass("hover"); if( $(this).next('.subitems')[0].clientHeight > height()){ $(this).next('.subitems').height(height()); } var top = this.offsetTop; $(this).next('.subitems')[0].style.top = 0;//top - $(this).next('.subitems').height(); if($(this).next('.subitems')[0].offsetTop + $(this).next('.subitems').height() - $(this).height() < top){ $(this).next('.subitems')[0].style.top = Math.floor(top - $(this).next('.subitems').height() + $(this).height()) + 'px'; } $(".dd-inner").find(".subitems").not($(this).next(".subitems")).addClass("hide"); } $(".dd-inner")[0].style.overflow='scroll'; });$(".link").click(function(e){//三级导航 e.stopPropagation(); $this = $(this); $next = $this.next(".submenu"); if(!$this.parent().is(".open")){ $next.slideToggle('nomal', function(){ if($this.parents('.subitems').height() > height()){ $this.parents('.subitems').height(height()); } }); $this.parent().toggleClass('open'); $("#accordion").find('.submenu').not($next).slideUp().parent().removeClass('open'); $(".dd-inner")[0].style.overflow='scroll'; }else{ $next.slideUp().parent().removeClass('open'); } }); $(".dd-inner").click(function(){ if(!$(".dd").is(".hide")){ $(".dd").addClass("hide"); } $(".subitems").each(function(){ if(!$(this).is(".hide")){ $(this).addClass("hide"); } }); move(); $('#all').css('pointer-events', 'none'); setTimeout(function(){ $('#all').css('pointer-events', 'auto'); }, 301);//防止底层元素点击穿透事件 }); $("#bg").click(function(){ if(!$(".dd").is(".hide")){ $(".dd").addClass("hide"); } $(".subitems").each(function(){ if(!$(this).is(".hide")){ $(this).addClass("hide"); } }); move(); $('#all').css('pointer-events', 'none'); setTimeout(function(){ $('#all').css('pointer-events', 'auto'); }, 301);//防止底层元素点击穿透事件 });
4.这个是最容易忽略的一点定位的说明:position:absolute的子元素的高度是不能赋予它的父类的。换句话说就是如果一个元素的height:auto,而子元素是absolute的,那么这个元素的高度是0px,是看不到的,因为子元素不能撑起父元素。
5.这个我在之前的文章也说过,这里既然是总结文章,那么也顺便说一下,在页面上使用ajax的时候生成html内容时,如果需要用jquery选择器为这些ajax生成的html内容添加js事件,一定要在这些html内容已经被生成之后才能使用。不然是不会起效果的,因为jquery选择器无法选择还没生成的html内容
6.children()和find()的区别:children()不会给子元素排序进行区分,所以没办法对多个同一种标签的子元素分别添加不同的样式。 find()会给子元素进行排序区分。可以对特定的某个子元素单独添加样式
总结下来,我遇到的移动web的坑大概就是这么多,以后如果还遇到了,我会再来补充的,如果你们也有其他的坑,也可以分享分享,共同学习交流。
- 浅谈项目中遇到的关于移动web的JS坑
- 最近移动前端项目中遇到的两个坑
- Web Uploader项目实战中遇到的诸多坑
- 在项目中遇到的一些关于vue的坑
- 浅谈UE4项目打包中遇到的几个问题
- 【Web前端】Vue.js 项目中遇到的一些问题汇总
- 关于移动iscroll项目中使用的一些坑
- 在项目中遇到的坑(关于静态变量)
- 移动端web整理 移动端问题总结,移动web遇到的那些坑
- 关于eclipse下maven、tomcat、web项目遇到的问题
- 移动端web页面开发中遇到的三个“小坑”
- 项目中遇到的坑~
- java web项目中所遇到的编码问题
- Mondrian集成WEB项目中所遇到的问题
- java转web项目中遇到的问题及解决
- 第一个java Web项目中遇到的问题(上)
- 项目中遇到的bug(web前端-持续更新)
- MyEclipse中开发web项目遇到的一些问题
- java的构造方法链
- Git的Patch功能
- 扩展grep(grep -E 或者 egrep)
- java String详解
- 二叉树的建立与DFS遍历
- 浅谈项目中遇到的关于移动web的JS坑
- Eclipse中设置工程所有文件编码格式为utf-8
- 错误之-Error:Execution failed for task ':app:mergeDebugResources'
- mysql中的常用函数
- ubuntu自带VI编辑器不好用的解决办法
- 当读/写磁盘文件时,read/write是不带缓冲机制的吗?请说明原因。
- 简单模仿百度首页——有一些问题待解决
- Vue从入门到精通(6)--第四阶段(中):填坑
- Android listview+SwipeRefreshLayout 下拉刷新,上拉加载.