Window.matchmedia监听器触发两次

时间:2017-06-29 16:51:54

标签: javascript ecmascript-6 matchmedia

我正在尝试编写一些javascript,它将更改某些浏览器断点处JS配置对象中保存的某些值。

我已经在配置对象中存储了window.matchmedia测试,然后我循环遍历这个对象的键,为每个测试添加一个事件监听器,如下所示:

Object.keys(config.mediaQueries).map((key) =>{
     config.mediaQueries[key].addListener(function(){
         console.log("breakpoint change");
     });
});

https://codepen.io/decodedcreative/pen/YQpNVO

但是,当调整浏览器大小并运行这些侦听器回调函数时,它们似乎运行了两次。在您的控制台打开的情况下检查上面的CodePen,您将看到我的意思。

有谁知道我在这里做错了什么?

4 个答案:

答案 0 :(得分:4)

要回答你的直接问题,你没有做错任何事。 JS正在做它应该做的事情。

trld 有2个事件正在触发,但只有一个事件包含匹配的媒体查询。

正在发生的事情是,当浏览器遇到断点时,会记录2个事件。举个例子,让我们考虑一下将浏览器的大小从1250px调整到1150px的情况。当窗口的宽度达到1199px时,你的功能是:

Object.keys(config.mediaQueries).map((key) =>{
  config.mediaQueries[key].addListener(function(event){
    console.log("breakpoint change");
  });
});

将记录2个事件。如果您深入了解并使用以下内容记录事件:

Object.keys(config.mediaQueries).map((key) =>{
  config.mediaQueries[key].addListener(function(event){
    console.log(event);
  });
});

您会看到有关媒体查询的更多信息。我把事件对象煮成了下面的重要道具。

// First event
matches: true
media: "(max-width: 1199px) and (min-width: 992px)"

// Second event
matches: false
media: "(min-width: 1200px)"

这里发生的事情是记录了2个事件,但只有一个事件包含匹配的查询。

因此,如果我们想改进您的脚本以进行日志记录,您可以检查matches属性:

Object.keys(config.mediaQueries).map((key) =>{
  config.mediaQueries[key].addListener(function(event){
    if (event.matches) { 
      console.log(event);
    }
  });
});

通过这个小的更改,只会记录匹配的媒体查询。

答案 1 :(得分:2)

如果您将console.log("breakpoint change");更改为console.log(key, "breakpoint change");,则会在手动调整浏览器窗口大小时看到xss查询都被触发。< / p>

如果您只希望在时间窗口内触发一次回调,则需要限制事件或以其他方式实现行为。

修改:Tomasz BubałaBrett DeWoody的答案都指向event.matches属性作为此问题的正确解决方案.matchMedia

答案 2 :(得分:1)

似乎事件在调整大小之前和调整大小之后就开始了。如果要在更改后立即更改“断点”,请添加if语句。

编辑:Noah Freitas在调整大小时触发2个键的事件可能是正确的。如果e.matches与键匹配,则返回true,因此它应该可以正常工作

    function(e) {
      if(e.matches) {
        console.log("breakpoint change");
      }
    }

答案 3 :(得分:0)

不确定,如果这已经是完整的答案。但你是对的。回调发射两次 - 两个不同的键。

我修改了您的示例,因此输出key

Object.keys(config.mediaQueries).map((key) =>{
    console.log("register key: '" + key + "'");
    config.mediaQueries[key].addListener(function(){
        console.log("breakpoint change key:'" + key + "'");
    });
});

生成的日志输出始终生成两行:

breakpoint change key:'m'
breakpoint change key:'l'

或减少宽度:

breakpoint change key:'s'
breakpoint change key:'m'