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

时间:2018-04-23 20:49:28

标签: javascript media-queries

我注意到css媒体查询定义和javascript window.matchMedia媒体查询定义之间存在差异:

css规则最初适用于已加载的页面。

javascript中定义的规则在页面加载后不会执行,但只有在输入新条件后才会执行。

一个例子:

我有两个不同的页面,它们具有相同的媒体查询定义,第一个在css中定义,第二个在javascript中定义:

css版本(在样式元素中定义):

@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";
  }
});

当我加载页面并且窗口宽度为700像素

  • css版本页面为蓝色
  • javascript版本为白色,仅在满足新条件后更改其状态,即窗口大小低于601像素。

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

4 个答案:

答案 0 :(得分:3)

为了能够在加载时触发matchMedia,您可以将其设置为这样。

Stack snippet

<!DOCTYPE html>
<html>

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

    <script>
      document.addEventListener("DOMContentLoaded", function(e) {
      
        var mql1 = window.matchMedia("(max-width: 400px)");
        function handleMQL1(mql) {
          if (mql.matches) {
            console.log("CALLBACK (max-width: 400px)");
            document.body.style.background = "green";
          }
        }
        mql1.addListener(handleMQL1);
        handleMQL1(mql1);                // fire once, on load
        

        var mql2 = window.matchMedia("(min-width: 401px) and (max-width: 600px)");
        function handleMQL2(mql) {
          if (mql.matches) {
            console.log("CALLBACK (max-width: 600px)");
            document.body.style.background = "red";
          }
        }
        mql2.addListener(handleMQL2);
        handleMQL2(mql2);                // fire once, on load
        

        var mql3 = window.matchMedia("(min-width: 601px) and (max-width: 800px)");
        function handleMQL3(mql) {
          if (mql.matches) {
            console.log("CALLBACK (max-width: 800px)");
            document.body.style.background = "blue";
          }
        }
        mql3.addListener(handleMQL3);
        handleMQL3(mql3);                // fire once, on load


        var mql4 = window.matchMedia("(min-width: 801px)");
        function handleMQL4(mql) {
          if (mql.matches) {
            console.log("CALLBACK (min-width: 801px)");
            document.body.style.background = "gray";
          }
        }
        mql4.addListener(handleMQL4);
        handleMQL4(mql4);                // fire once, on load
      });
      
      function showSize() {
        console.log("window.innerWidth: " + window.innerWidth);
      }

    </script>
  </head>

  <body>
  </body>

</html>

这是一个更新版本,设置了一些更清洁

单位。 src:http://www.javascriptkit.com/javatutors/matchmediamultiple.shtml

<!DOCTYPE html>
<html>

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

    <script>
      document.addEventListener("DOMContentLoaded", function(e) {
      
        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)")
        ]

        // call once on load
        mqh();
        
        for (var i=0; i<mqls.length; i++){
          mqls[i].addListener(mqh)
        }
        
        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);
        }
      });
      
    </script>
  </head>

  <body>
  </body>

</html>

答案 1 :(得分:2)

在页面加载时不会调用绑定到window.matchMedia的回调函数。

问题的解决方案是:

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

答案 2 :(得分:1)

我今天也面临着同样的问题,并且我使用了以下受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>

核心概念是使用MediaQueryList.matches作为参数传递一次运行您的侦听器功能。

如果有人试图通过框架实现这一目标,请记住在组件安装事件期间注册并触发侦听器。

答案 3 :(得分:-1)

我认为我们可以使其变得更容易

我将其留在这里。

function testMediaQuery (media, callback){

    let mql = window.matchMedia(media);

    mql.addListener(function(event){

        return callback(event.matches)
    })

    callback(mql.matches)
}

testMediaQuery(`(min-width: 600px)`, function(matches){

    if (matches){

        console.log(`I'm larger than 600px`)
    }
    else{

        console.log(`I'm smaller than 600px`)
    }
})

你可以做到

let mqlDesktop = `(min-width: 701px)`,
    mqlTablet = `(min-width: 576px) and (max-width: 700px)`,
    mqlMobile = `(max-width: 575px)`;


function testMediaQuery (media, callback){

    let mql = window.matchMedia(media);

    mql.addListener(function(event){

        return callback(event.matches)
    })

    callback(mql.matches)
}



testMediaQuery(mqlDesktop, function(matches){

    if (matches){

        console.log(`DESKTOP`)
    }
})

testMediaQuery(mqlTablet, function(matches){

    if(matches){

        console.log(`TABLET`)
    }
})

testMediaQuery(mqlMobile, function(matches){

    if(matches){

        console.log(`MOBILE`)
    }
})