Window.matchmedia 监听器触发两次
Window.matchmedia listener firing twice
我正在尝试编写一些 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,您就会明白我的意思。
有谁知道我在这里做错了什么?
似乎事件在调整大小之前和调整大小之后触发。如果要在更改后立即记录 "breakpoint" 更改,请添加 if 语句。
编辑:Noah Freitas 关于调整大小时触发 2 个键的事件可能是正确的。如果它与密钥匹配,仍然 e.matches returns 正确,因此它应该可以正常工作
function(e) {
if(e.matches) {
console.log("breakpoint change");
}
}
如果您将 console.log("breakpoint change");
更改为 console.log(key, "breakpoint change");
,您会看到当您手动调整浏览器大小时 xs
和 s
查询都会被触发 window.
如果您只希望回调在一段时间内触发一次 window,您需要限制事件或以其他方式实现行为。
编辑:Tomasz Bubała and Brett DeWoody 的回答都指向 event.matches
属性 作为此问题的正确且更 .matchMedia
具体的解决方案。
不确定,这是否已经是完整答案。但你是对的。回调触发两次 - 针对两个不同的键。
我修改了你的例子,所以它输出 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'
回答你的直接问题,你没有做错任何事。 JS 正在做它应该做的事情。
trld 触发了 2 个事件,但只有一个包含匹配的媒体查询。
发生的事情是,当浏览器遇到断点时,会记录 2 个事件。例如,让我们考虑将浏览器的大小从 1250 像素调整为 1150 像素的情况。当 window 的宽度达到 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);
}
});
});
通过这个小改动,只会记录匹配的媒体查询。
我正在尝试编写一些 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,您就会明白我的意思。
有谁知道我在这里做错了什么?
似乎事件在调整大小之前和调整大小之后触发。如果要在更改后立即记录 "breakpoint" 更改,请添加 if 语句。
编辑:Noah Freitas 关于调整大小时触发 2 个键的事件可能是正确的。如果它与密钥匹配,仍然 e.matches returns 正确,因此它应该可以正常工作
function(e) {
if(e.matches) {
console.log("breakpoint change");
}
}
如果您将 console.log("breakpoint change");
更改为 console.log(key, "breakpoint change");
,您会看到当您手动调整浏览器大小时 xs
和 s
查询都会被触发 window.
如果您只希望回调在一段时间内触发一次 window,您需要限制事件或以其他方式实现行为。
编辑:Tomasz Bubała and Brett DeWoody 的回答都指向 event.matches
属性 作为此问题的正确且更 .matchMedia
具体的解决方案。
不确定,这是否已经是完整答案。但你是对的。回调触发两次 - 针对两个不同的键。
我修改了你的例子,所以它输出 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'
回答你的直接问题,你没有做错任何事。 JS 正在做它应该做的事情。
trld 触发了 2 个事件,但只有一个包含匹配的媒体查询。
发生的事情是,当浏览器遇到断点时,会记录 2 个事件。例如,让我们考虑将浏览器的大小从 1250 像素调整为 1150 像素的情况。当 window 的宽度达到 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);
}
});
});
通过这个小改动,只会记录匹配的媒体查询。