javascript - jQuery window.matchMedia 冲突函数

标签 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/

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

最佳答案

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

<小时/>

但是,让我们对所有这些代码进行更多清理,冒着变得有点冗长的风险:

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

相反,因为您已经在使用 MediaQuery API ,充分使用它并将您的函数挂接到其 onchange 中处理程序。
另外,根据您的查询,需要一个。它要么匹配一个,要么匹配另一个 (如果您确实需要检查“(仅屏幕)”,我建议为此进行另一个查询,但有它在文档的生命周期中以有意义的方式发生变化的可能性很小)。

<小时/>

现在我们已经正确处理了 MediaQuery 更改,是时候更改 $.hover$.click 处理程序了:
您可以在每次返回移动 View 时将其删除,并在转到桌面 View 时再次添加它,但更简洁的方式 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>

关于javascript - jQuery window.matchMedia 冲突函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48760984/

相关文章:

jquery - 数据表插件 - jquery - 列大小调整相对于其他列进行调整。如何避免这种情况?

javascript - 即使在 javascript 中保存了数据的副本,数据还是空的

javascript - svg 圆形路径动画

使用 smarty 添加表单名称时出现 Javascript 连接错误

添加的 html 不会执行 Javascript

jquery - jquery 中是否有一个函数,如果至少一个 Deferreds 得到解决,则返回一个 promise ?

javascript - 不能使用文本区域中的 Enter 键

javascript - 对下划线模板使用多个数据源

jQuery 选择器?

jquery - 我可以将Class直接添加到容器中的img标签吗?