浅谈项目中遇到的关于移动web的JS坑

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_29673403/article/details/70226567

因为项目需要,自己设计并构建了很多手机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的坑大概就是这么多,以后如果还遇到了,我会再来补充的,如果你们也有其他的坑,也可以分享分享,共同学习交流。

猜你喜欢

转载自blog.csdn.net/sinat_29673403/article/details/70226567
今日推荐