jQuery window.matchMedia冲突函数

时间:2018-02-13 06:48:11

标签: javascript jquery

努力了解这实际上是如何运作的。代码按预期工作,但由于某些原因,当窗口调整大小,并且新函数被触发时,旧的函数仍然会触发,所以它很乱。 : - /

我确定有更好的方法来写这个。我只想要" isMobile"在max-width:1024和" isNotMobile"时运行当max-width大于1024时,但只有一个在运行,而不是同时运行。有更好的方法吗?

$(document).ready(function(){
    $(window).resize(function() {

        var isMobile = window.matchMedia("only screen and (max-width: 1024px)");
        var isNotMobile = window.matchMedia("only screen and (min-width: 1024px)");

        if (isMobile.matches) {
            $('#wpi-page-left').removeClass("active");
            $('#wpi-page-left').addClass("not-active");

            $( '#wpi-page-center' ).click(function(e) {
                var $this = $('#wpi-page-left');
                if ($this.hasClass('active')) {
                    $('#wpi-page-left').removeClass('active');
                    $('#sidebar').removeClass('active');
                    $('#wpi-page-left').addClass('not-active');
                }
            });
            $( '#mobile-toggle-btn' ).click(function(e){
                var $this = $('#wpi-page-left');
                if ($this.hasClass('not-active')) {
                    $('#wpi-page-left').removeClass('not-active');
                    $('#wpi-page-left').addClass('active');
                    $('#sidebar').addClass('active');
                } else if ($this.hasClass('active')) {
                    $('#wpi-page-left').removeClass('active');
                    $('#sidebar').removeClass('active');
                    $('#wpi-page-left').addClass('not-active');
                }
            });
        } else if (isNotMobile.matches) {
            setTimeout(function() {
                $( '#wpi-page-left' ).removeClass( 'active' );
            }, 1000);

            var timer;
            var delay = 350;

            $('#wpi-page-left').hover(function() {
                timer = setTimeout(function() {
                    $('#wpi-page-left').addClass( 'active' );
                    $('#wpi-page-left').removeClass( 'not-active' );
                }, delay);
            }, function() {
                $('#wpi-page-left').removeClass( 'active' );
                $('#wpi-page-left').addClass( 'not-active' );
                clearTimeout(timer);
            });
       }
      $("#dimensions").html($(window).width());
}).resize();

});

更新

这是一个显示问题的FIDDLE: https://jsfiddle.net/hwqegaza/9/

我在我的小提琴中添加了说明,但基本上是加载页面,将鼠标悬停在栏上或单击移动版本(取决于加载页面的宽度),现在调整页面大小并尝试使用不同版本的菜单。您将看到两个版本都在运行。 : - /

2 个答案:

答案 0 :(得分:1)

您的主要问题是您要多次添加$.hover个事件处理程序,而不会删除它们,因此即使您将它们附加到桌面视图中,它们仍然在移动视图中处于活动状态。

但是,让我们在所有这些代码中做更多的清理工作,冒着变得有点冗长的风险:

首先,尽可能避免挂钩resize事件,或仅执行最少的任务。此事件可能会以很高的速率发射(可能>每秒100次),并且以这样的频率操纵DOM会导致瓶颈,更不用说添加新的事件处理程序......

相反,由于您已经在使用MediaQuery API,因此请充分使用它并在onchange处理程序中挂钩您的函数。
另外,根据您的查询,需要一个查询。要么它匹配一个,要么匹配另一个(如果你真的需要检查' (只有屏幕)',我会建议做另一个查询为此,但在文件的生命周期内以有意义的方式改变的可能性很小。)

现在我们确实正确处理了MediaQuery更改,现在是时候更改$.hover$.click处理程序了:
您可以在每次返回移动视图时将其删除,并在转到桌面视图时再次添加它,但更简洁的方式是IMO只将这些事件附加一次,并简单地处理处理函数本身的两种情况,然后退出在错误的观点中提前过早。

它可能会给我们类似的东西



$(document).ready(function() {
  // a single MediaQuery
  var isMobile = window.matchMedia("only screen and (max-width: 800px)");
  // toggle the classes when our MediaQuery will change
  isMobile.onchange = toggleMobile;
  toggleMobile(); // do the initial one

  function toggleMobile() {
    if (isMobile.matches) {
      $('#wpi-page-left').removeClass("active");
      $('#wpi-page-left').addClass("not-active");

      $('#wpi-page-center').click(function(e) {
        var $this = $('#wpi-page-left');
        if ($this.hasClass('active')) {
          $('#wpi-page-left').removeClass('active');
          $('#sidebar').removeClass('active');
          $('#wpi-page-left').addClass('not-active');
        }
      });
    } else { // if we're not in mobile, then we are in desktop
      setTimeout(function() {
        $('#wpi-page-left').removeClass('active');
      }, 1000);
    }
    $("#dimensions").html(isMobile.matches ? 'Mobile' : 'Desktop');
  };

  // this needs to be called only once
  (function attachHoverHandlers() {
    var timer;
    var delay = 350;
    // attach the event listeners
    $('#wpi-page-left').hover(onhoverin, onhoverout);

    function onhoverin() {
      if (isMobile.matches) return; // if mobile view, then do nothing

      timer = setTimeout(function() {
        $('#wpi-page-left').addClass('active');
        $('#wpi-page-left').removeClass('not-active');
      }, delay);
    }

    function onhoverout() {
      if (isMobile.matches) return; // if mobile view, then do nothing

      $('#wpi-page-left').removeClass('active');
      $('#wpi-page-left').addClass('not-active');
      clearTimeout(timer);
    }
  })();

  // So does this
  $('#mobile-toggle-btn').click(handleMobileClick);

  function handleMobileClick(e) {
    if (!isMobile.matches) return;

    var $this = $('#wpi-page-left');
    if ($this.hasClass('not-active')) {
      $('#wpi-page-left').removeClass('not-active');
      $('#wpi-page-left').addClass('active');
      $('#sidebar').addClass('active');
    } else if ($this.hasClass('active')) {
      $('#wpi-page-left').removeClass('active');
      $('#sidebar').removeClass('active');
      $('#wpi-page-left').addClass('not-active');
    }
  }
})

html,
body {
  display: flex;
  flex-direction: row;
  height: 100vh;
  width: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
  font-family: helvetica;
}

.label {
  padding-left: 5px;
}

#wpi-page-left {
  flex: 0 80px;
  width: 80px;
  background: #2E323C;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-transition: all 0.15s ease;
  -moz-transition: all 0.15s ease;
  -ie-transition: all 0.15s ease;
  -o-transition: all 0.15s ease;
  transition: all 0.15s ease;
}

#wpi-page-left .fa,
#wpi-page-left .label {
  color: #FFF;
}

#wpi-page-left ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
}

#wpi-page-left ul>li a {
  display: inline-block;
  color: #e6e6e6;
  text-decoration: none;
  padding: 8px 0;
  width: 100%;
}

#wpi-page-left ul>li a:hover {
  color: #FFF;
  background: #181a1f;
}

#wpi-page-left #wrap-menu {
  display: flex;
  flex-direction: column;
  flex: 1 auto;
  height: 100%;
}

#wpi-page-left #wrap-menu #logo {
  flex: 0 auto;
  display: none;
  margin: 10px 0;
}

#wpi-page-left #wrap-menu #logo-inactive {
  flex: 0 auto;
  text-align: center;
  width: 100%;
  margin: 10px 0;
}

#wpi-page-left #wrap-menu #menu {
  display: flex;
  flex-direction: column;
  flex: 1 auto;
}

#wpi-page-left #wrap-menu #menu ul#sidebar {
  flex: 1 250px;
}

#wpi-page-left #wrap-menu #menu ul#sidebar>li a {
  padding: 8px;
}

#wpi-page-left #wrap-menu #menu ul#sidebar #mobile-logo-ext {
  display: none;
}

#wpi-page-left #wrap-menu #menu ul#mobile-bar {
  list-style-type: none;
  margin: 10px 0 60px 0;
  display: none;
  width: 60px;
}

#wpi-page-left #wrap-menu #menu ul#mobile-bar>li {
  width: 100%;
}

#wpi-page-left ul#sidebar {
  display: none;
}

#wpi-page-left ul#sidebar-inactive {
  display: block;
}

#wpi-page-left ul#sidebar-inactive>li {
  text-align: center;
}

#wpi-page-left.active {
  flex: 0 210px;
  width: 210px;
}

#wpi-page-left.active #wrap-menu #logo {
  display: block;
}

#wpi-page-left.active #wrap-menu #logo-inactive {
  display: none;
}

#wpi-page-left.active #wrap-menu ul#sidebar {
  display: block;
}

#wpi-page-left.active #wrap-menu ul#sidebar-inactive {
  display: none;
}

#wpi-page-center {
  display: flex;
  flex-direction: column;
  flex: 1;
  background: #F1F5FA;
  overflow-y: auto;
  padding: 10px;
}

#wpi-page-center .panel {
  flex: 1 auto;
  background: #FFF;
  border: 1px solid #cbdaed;
  padding: 10px;
}

@media screen and (max-width: 800px) {
  #wpi-page-left {
    flex: 0 80px;
    width: 80px;
    overflow: hidden;
  }
  #wpi-page-left #logo {
    display: none;
  }
  #wpi-page-left #logo-inactive {
    display: none;
  }
  #wpi-page-left #wrap-menu {
    display: flex;
    flex-direction: column;
    flex: 1 auto;
    height: 100%;
    min-width: 80px;
  }
  #wpi-page-left #wrap-menu #logo {
    flex: 0 auto;
  }
  #wpi-page-left #wrap-menu #logo-inactive {
    flex: 0 auto;
  }
  #wpi-page-left #wrap-menu #menu {
    display: flex;
    flex-direction: column;
    flex: 1 auto;
    min-width: 80px;
  }
  #wpi-page-left #wrap-menu #menu ul#mobile-bar {
    display: block;
    position: relative;
    z-index: 120;
    background: #2E323C;
    flex: 1 80px;
    width: 80px;
    padding: 0;
    margin: 0;
    border-right: 1px solid #181a1f;
    height: 100%;
  }
  #wpi-page-left #wrap-menu #menu ul#mobile-bar li {
    width: 100%;
    text-align: center;
  }
  #wpi-page-left #wrap-menu #menu ul#mobile-bar li:first-child {
    text-align: center;
    height: 61px;
    padding: 10px 0;
    border-bottom: 1px solid #181a1f;
  }
  #wpi-page-left #wrap-menu #menu ul#mobile-bar li:nth-child(2) {
    margin-top: 10px;
    padding-top: 8px;
    padding-bottom: 8px;
  }
  #wpi-page-left #wrap-menu #menu ul#mobile-bar li a {
    display: inline-block;
    border-width: 0;
    background: transparent;
    width: 100%;
    padding: 8px 0;
    color: whitesmoke;
  }
  #wpi-page-left #wrap-menu #menu ul#mobile-bar li a:hover {
    color: #FFF;
  }
  #wpi-page-left #wrap-menu #menu ul#sidebar {
    position: fixed;
    background: #2E323C;
    left: -330px;
    top: 0;
    bottom: 0;
    margin: 0;
    padding-top: 5px;
    z-index: 100;
    flex: 1 250px;
    width: 250px;
    overflow-x: hidden;
    -webkit-transition: all 0.15s ease;
    -moz-transition: all 0.15s ease;
    -ie-transition: all 0.15s ease;
    -o-transition: all 0.15s ease;
    transition: all 0.15s ease;
  }
  #wpi-page-left #wrap-menu #menu ul#sidebar.active {
    left: 80px;
    overflow-y: auto;
  }
  #wpi-page-left #wrap-menu #menu ul#sidebar li#mobile-logo-ext {
    display: block;
    overflow: visible;
  }
  #wpi-page-left #wrap-menu #menu ul#sidebar-inactive {
    display: none;
  }
  #wpi-page-left #wrap-menu #menu.active ul#sidebar {
    left: 50px;
    order: 2;
  }
  #wpi-page-left.active {
    flex: 0 80px;
    width: 80px;
  }
  #wpi-page-left.active #wrap-menu #logo {
    display: none;
    flex: 0 auto;
  }
  #wpi-page-left.active #wrap-menu #logo-inactive {
    display: none;
    flex: 0 auto;
  }
}

<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wpi-page-left">
  <div id="wrap-menu">
    <div id="logo">
      <span class="fa fa-css3 fa-2x"></span><span class="label">COMPANY NAME</span>
    </div>
    <div id="logo-inactive">
      <span class="fa fa-css3 fa-2x"></span>
    </div>
    <div id="menu">
      <ul id="mobile-bar">
        <li>
          <span class="fa fa-css3 fa-2x"></span>
        </li>
        <li>
          <a id="mobile-toggle-btn" href="#!"><i class="fa fa-bars fa-fw fa-lg"></i></a>
        </li>
      </ul>
      <ul id="sidebar">
        <li id="mobile-logo-ext">
          <span class="label">COMPANY</span>
        </li>
        <li id="item1">
          <a href="#!">
            <span class="fa fa-file-word-o fa-fw"></span><span class="label">Menu Item 1</span>
          </a>
        </li>
        <li id="item2">
          <a href="#!">
            <span class="fa fa-file-archive-o fa-fw"></span><span class="label">Menu Item 2</span>
          </a>
        </li>
        <li id="item3">
          <a href="#!">
            <span class="fa fa-file-pdf-o fa-fw"></span><span class="label">Menu Item 3</span>
          </a>
        </li>
        <li id="item4">
          <a href="#!">
            <span class="fa fa-file-code-o fa-fw"></span><span class="label">Menu Item 4</span>
          </a>
        </li>
      </ul>
      <ul id="sidebar-inactive">
        <li id="item1">
          <a href="#!">
            <span class="fa fa-file-word-o fa-fw"></span>
          </a>
        </li>
        <li id="item2">
          <a href="#!">
            <span class="fa fa-file-archive-o fa-fw"></span>
          </a>
        </li>
        <li id="item3">
          <a href="#!">
            <span class="fa fa-file-pdf-o fa-fw"></span>
          </a>
        </li>
        <li id="item4">
          <a href="#!">
            <span class="fa fa-file-code-o fa-fw"></span>
          </a>
        </li>
      </ul>
    </div>
  </div>
</div>
<div id="wpi-page-center">
  <div class="panel">
    <h2>Page mode: <span id="dimensions"></span></h2>
    <p>
      Resize from above 800px to below 800px, or vice versa. You'll see that both are running. The hover stuff shouldn't be active when below 800px, but it is... :(
    </p>
  </div>
</div>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

您必须向当前窗口的resize事件添加事件侦听器才能使其正常工作。 您的代码意味着只有在DOM准备就绪时才执行检查,这就是每次视口宽度发生变化时需要重新加载的原因。

$(window).resize(function() {
  // your code
  // e.g check the width: console.log($(this).innerWidth());
});
// OR
$(window).resize(() => console.log($(this).innerWidth()))

jQuery docs on resize

MDN window.innerWidth docs