浅谈项目中遇到的关于移动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的坑大概就是这么多,以后如果还遇到了,我会再来补充的,如果你们也有其他的坑,也可以分享分享,共同学习交流。

0 0
原创粉丝点击