admin管理员组文章数量:1327093
I'm trying to write some javascript which will change some values held within a JS config object at certain browser breakpoints.
I have stored the window.matchmedia tests within the config object and then I'm looping over this object's keys to add an event listener to each test like so:
Object.keys(config.mediaQueries).map((key) =>{
config.mediaQueries[key].addListener(function(){
console.log("breakpoint change");
});
});
However when the browser is resized and these listener callback functions run, they appear to run twice. Check the CodePen above with your Console open and you'll see what I mean.
Does anyone know what I've done wrong here?
I'm trying to write some javascript which will change some values held within a JS config object at certain browser breakpoints.
I have stored the window.matchmedia tests within the config object and then I'm looping over this object's keys to add an event listener to each test like so:
Object.keys(config.mediaQueries).map((key) =>{
config.mediaQueries[key].addListener(function(){
console.log("breakpoint change");
});
});
https://codepen.io/decodedcreative/pen/YQpNVO
However when the browser is resized and these listener callback functions run, they appear to run twice. Check the CodePen above with your Console open and you'll see what I mean.
Does anyone know what I've done wrong here?
Share Improve this question asked Jun 29, 2017 at 16:51 James HowellJames Howell 1,4525 gold badges26 silver badges46 bronze badges4 Answers
Reset to default 6 +50To answer your direct question, you haven't done anything wrong. And the JS is doing exactly what it's supposed to do.
trld There are 2 events firing but only one contains a matching media query.
What's happening is that when the browser hits a breakpoint there are 2 events being logged. As an example, let's consider the case of when the browser is being resized from 1250px down to 1150px. When the window hits 1199px in width your function:
Object.keys(config.mediaQueries).map((key) =>{
config.mediaQueries[key].addListener(function(event){
console.log("breakpoint change");
});
});
will log 2 events. If you dive into this deeper and log the events with:
Object.keys(config.mediaQueries).map((key) =>{
config.mediaQueries[key].addListener(function(event){
console.log(event);
});
});
you'll see some more information on the media queries. I've boiled the event object down to the important props below.
// First event
matches: true
media: "(max-width: 1199px) and (min-width: 992px)"
// Second event
matches: false
media: "(min-width: 1200px)"
What's happening here is 2 events are being logged, but only one of the events contains the matching query.
So, if we wanted to improve your script for logging, you could check the matches
property:
Object.keys(config.mediaQueries).map((key) =>{
config.mediaQueries[key].addListener(function(event){
if (event.matches) {
console.log(event);
}
});
});
With this small change only the matching media query will be logged.
If you change your console.log("breakpoint change");
to console.log(key, "breakpoint change");
, you'll see that both the xs
and s
queries are being triggered when you manually resize the browser window.
If you only want your callback to fire once within a time window, you'll need to throttle the events or achieve the behavior in some other way.
Edit: Tomasz Bubała and Brett DeWoody's answers both point to the event.matches
property as the proper and more .matchMedia
specific solution to this problem.
Seems like the event is firing just before resizing and right after resizing. Add an if statement if you want to log "breakpoint" change right after it changed.
Edit: Noah Freitas might be right about the event firing for 2 keys when resizing. Still e.matches returns true if it matches the key so it should work fine
function(e) {
if(e.matches) {
console.log("breakpoint change");
}
}
Not sure, if this is already the full answer. But you are right. The callback is fireing twice - for two different keys.
I modified your example, so it outputs the key
:
Object.keys(config.mediaQueries).map((key) =>{
console.log("register key: '" + key + "'");
config.mediaQueries[key].addListener(function(){
console.log("breakpoint change key:'" + key + "'");
});
});
The resulting logging output always produces two lines:
breakpoint change key:'m'
breakpoint change key:'l'
Or for decreased width:
breakpoint change key:'s'
breakpoint change key:'m'
本文标签: javascriptWindowmatchmedia listener firing twiceStack Overflow
版权声明:本文标题:javascript - Window.matchmedia listener firing twice - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742206907a2432985.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论