如何在 JavaScript 中使用媒體查詢

2023-03-03 18:01:15

前言

說起媒體查詢想必大家最先想到的都是CSS中@media,沒錯,這是我們最常用的媒體查詢方法,主要用來為我們的網站做適配處理。

比如:

h1 {
  font-size: 2rem;
  color: green;
}
@media (min-width: 600px) {
  h1 {
    font-size: 4rem;
  }
}

我們使用 CSS 告訴瀏覽器標題需要為綠色,字型大小為 2rem。但是當螢幕寬度超過 600px 時,字型大小需要增加到 4rem。

上面這種方式相信大家都並不陌生,現在我們再來嘗試另外一種媒體查詢的方法。

在JavaScript中使用媒體查詢

我們可以在 JavaScript 程式碼中使用與上面相同的媒體查詢。主要API就是 ----matchMedia()

Window.matchMedia()

WindowmatchMedia() 方法返回一個新的 MediaQueryList物件,表示指定的媒體查詢 (en-US)字串解析後的結果。返回的 MediaQueryList 可被用於判定 Document 是否匹配媒體查詢,或者監控一個 document 來判定它匹配了或者停止匹配了此媒體查詢。(MDN)

語法

mqList = window.matchMedia(mediaQueryString)

引數

matchMedia()方法接受單個引數作為其值,即您要檢查的媒體查詢。

  • mediaQueryString:一個被用於媒體查詢解析的字串。

返回值

一個用來媒體查詢的新的MediaQueryList物件

它包含兩個屬性:

  • media,它將媒體查詢儲存為序列化字串

  • matches,它基本上是一個布林值,如果我們作為引數提供的媒體查詢與檔案匹配則返回true

呼叫matchMedia本身不會做太多的事情,並且我們只能在頁面載入時檢查是否滿足查詢條件,但如果我們想要在使用者改變螢幕大小時也能檢測到這種變化,在過去有兩種方法,稱為addListener()removeListener(),可以使用它們來監聽媒體查詢狀態的任何變化。但是,它們現在已被棄用。

現在我們應該考慮使用MediaQueryList addEventListener

addEventListener

matchMedia - change

<div id="show"></div>
<script>
  let mqList = window.matchMedia('(min-width: 600px)');
function widthChangeCallback(mqList) {
  console.log(mqList, '-')
  if(mqList.matches) {
    show.innerHTML = `<p class="large">我比599px大</p>`;
  } else {
    show.innerHTML = `<p class="small">我比599px小</p>`;
  }
}
widthChangeCallback(mqList)
mqList.addEventListener('change', widthChangeCallback);
</script>

當我們調整視窗大小時,這段程式碼會檢測螢幕寬度並更新文案

window - resize

看到這裡可能大家都想到了resize事件,沒錯該matchMedia()方法的另一種替代方法涉及將resize事件偵聽器附加到window,同樣能夠實現上面的效果。

function widthChangeCallback() {
  if(window.innerWidth > 599) {
    show.innerHTML = `<p class="large">我比599px大</p>`;
  } else {
    show.innerHTML = `<p class="small">我比599px小</p>`;
  }
}
window.addEventListener('resize', widthChangeCallback);
widthChangeCallback();

效能對比

既然兩種方案都能實現,所以我們很自然地想知道它們中的哪一個能提供更好的效能,以及我們應該在什麼時候使用這些解決方案中的每一個。

widthChangeCallback()每次調整視窗大小時,調整大小事件偵聽器都會觸發該函數。這僅在某些情況下需要響應視窗大小更改的每個範例,例如更新畫布。

但是,在某些情況下,只有當寬度或高度達到某個閾值時才需要發生某些事情。一個例子就是我們上面所做的文字更新。在這種情況下,matchMedia()將會獲得更好的效能,因為它僅在媒體查詢條件的實際更改時觸發回撥。

從上面我們可以看出兩者的回撥執行次數差異巨大,所以我們在開發過程中應當根據業務的實際需求去選擇使用哪一個API。

總結

我們瞭解到,藉助該matchMedia()方法,我們在 CSS 中經常使用的媒體查詢現在也可以在 JavaScript 中使用。並且使用matchMedia()可以為我們提供更好的效能,而不是在window 上新增事件偵聽器resize。與依賴於window做一些事情的舊方法相比,我們可以使用媒體查詢執行更多檢查。