javascript 如何强制匹配的window.matchMedia在页面加载时执行?

xsuvu9jc  于 2023-04-10  发布在  Java
关注(0)|答案(4)|浏览(119)

我注意到css媒体查询定义和javascript window.matchMedia媒体查询定义之间的差异:
css规则最初应用于加载的页面。
JavaScript中定义的规则不会在页面加载后执行,而只会在输入新条件后执行。
举个例子:
我有两个不同的页面,它们具有等效的媒体查询定义,第一个是用CSS定义的,第二个是用JavaScript定义的:
CSS版本(在style元素中定义):

@media (min-width: 401px) and (max-width: 600px) { body {background-color: red; } }
@media (min-width: 601px) and (max-width: 800px) { body {background-color: blue; } }

javascript版本(全局定义或在body onload之后调用的函数中定义):

window.matchMedia("(min-width: 401px) and (max-width: 600px)")
.addListener(function(e) {
  if (e.matches) {
    document.body.style.background = "red";
  }
});

window.matchMedia("(min-width: 601px) and (max-width: 800px)")
.addListener(function(e) {
  if (e.matches) {
    document.body.style.background = "blue";
  }
});

当我加载一个页面并且窗口是700px宽时

  • CSS版本页面是蓝色的
  • JavaScript版本是白色的,并且仅在满足新条件(即,窗口的大小小于601px)之后才改变其状态。

如何强制匹配的window.matchMedia在页面加载时执行?

9njqaruj

9njqaruj1#

要在加载时触发matchMedia,您可以这样做(使用稍微更干净的代码库)。
堆栈片段

<!DOCTYPE html>
<html>

  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <script>
      document.addEventListener("DOMContentLoaded", function(e) {
      
        // medias (as an array to make it a little easier to manage)
        var mqls = [
          window.matchMedia("(max-width: 400px)"),
          window.matchMedia("(min-width: 401px) and (max-width: 600px)"),
          window.matchMedia("(min-width: 601px) and (max-width: 800px)"),
          window.matchMedia("(min-width: 801px)")
        ]
        
        // event listeners
        for (var i=0; i<mqls.length; i++){
          mqls[i].addListener(mqh)
        }
        
        // matches methods
        function mqh(){
          if (mqls[0].matches) {
            console.log("CALLBACK (max-width: 400px)");
            document.body.style.background = "green";
          } else if (mqls[1].matches) {
            console.log("CALLBACK (max-width: 600px)");
            document.body.style.background = "red";
          } else if (mqls[2].matches) {
            console.log("CALLBACK (max-width: 800px)");
            document.body.style.background = "blue";
          } else if (mqls[3].matches) {
            console.log("CALLBACK (min-width: 801px)");        
            document.body.style.background = "gray";
          }
          console.log("window.innerWidth: " + window.innerWidth);
        }

        // call once on load
        mqh();
      });
      
    </script>
  </head>

  <body>
  </body>

</html>
x8diyxa7

x8diyxa72#

页面加载时不调用绑定到window.matchMedia的回调函数。
该问题的解决方案是:

  • 定义通过if(window.matchMedia("...").matches){明确检查媒体查询的函数
  • 通过<body onload在页面加载时调用该函数
  • 通过window.onresize在resize上调用该函数
ep6jt1vc

ep6jt1vc3#

我今天也遇到了同样的问题,我使用了以下受Nathan启发的解决方案:

const gate = 800

function listener(
  matches,
) {
  document.getElementById('tag').innerHTML = matches ? 'wider' : 'narrower'
}

window.onload=() => {
  const match = window.matchMedia(`(min-width: ${gate}px)`)
  match.addListener(e => listener(e.matches))
  listener(match.matches)
}
<h1>
  This window is 
  <span id='tag'></span>
  than 800px
</h1>

核心概念是运行一次listener函数,并将MediaQueryList.matches作为参数传递。
如果有人试图用框架实现这一点,请记住在组件安装事件期间注册并触发侦听器。

mrwjdhj3

mrwjdhj34#

这个方法对我很有效

function media(args, callback) {
let mqList = window.matchMedia(args);
function handle(mediaEvent) {
    if (mediaEvent.matches) {
        callback(mediaEvent)
    } else {
        callback(mediaEvent)
    }
}
mqList.addEventListener('change', handle);
handle(mqList) // Initial check
}

用途

media('(max-width: 920px)', (e) => {
    console.log(e.matches)//false/true
})

https://css-tricks.com/working-with-javascript-media-queries/开始

相关问题