2017-06-29 72 views
5

我想写一些JavaScript,它将改变某些浏览器断点处的JS配置对象内的某些值。Window.matchmedia监听器发射两次

我已存储的配置对象内的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

要回答你的直接问题,你没有做错任何事。 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); 
    } 
    }); 
}); 

有了这个小变化只有匹配的媒体查询将被记录。

+0

太棒了。谢谢你的帮助。 –

1

似乎事件正在调整大小之前和调整大小之后。如果要在更改后立即记录“断点”更改,请添加一条if语句。

编辑:诺亚弗雷塔斯可能是正确的事件触发2键调整大小。不过e.matches返回true,如果它是匹配的,因此如果您改变console.log("breakpoint change");console.log(key, "breakpoint change");应该正常工作

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

,你会看到,无论是xss查询被触发时,您手动调整浏览器窗口。

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

编辑:Tomasz BubałaBrett DeWoody的答案都指向event.matches属性作为适当的和更多的.matchMedia特定的解决方案来解决这个问题。

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'