📌

JSのレスポンシブ対応をresizeからmatchMediaに移行した

commits2 min read 2

JS でブレークポイント毎に処理を分ける場合の方法を resize から matchMedia に移行したので、その際のメモ書きです。

昔ながらの方法

恥ずかしながら、最近まで JS でブレークポイント毎に JS 処理を切り替える場合、
以下のように昔ながらの resize イベントの監視を使っていました...

昔ながらの方法
/**
 * イベントリスナー
 */
const listener = () => {
  // リサイズ時に行う処理

  if (window.innerWidth >= 768) {
    // 768px以上
    console.log('PC用ブレークポイント用処理');
  } else {
    // 768px未満
    console.log('SP用ブレークポイント用処理');
  }
};

// リスナー登録
window.addEventListener('resize', listener);

// 初期化処理
listener();

この方法は、リサイズの度にゴリゴリ listener 関数が実行されるので、できればやめたいと考えていました...💣

window.matchMedia をとりあえず使ってみた方法

以前、何かの記事で window.matchMedia を見かけたときは、以下のように CSS のメディアクエリと同じ記法で書けるので、いいなーぐらいの認識でした。

window.matchMediaをとりあえず使ってみた方法
/**
 * イベントリスナー
 */
const listener = () => {
  // リサイズ時に行う処理
  if (window.matchMedia('(min-width: 768px)').matches) {
    // 768px以上
    console.log('PC用ブレークポイント用処理');
  } else {
    // 768px未満
    console.log('SP用ブレークポイント用処理');
  }
};

// リスナー登録
window.addEventListener('resize', listener);

// 初期化処理
listener();

これなら (orientation: portrait) などデバイスの向きの判定もできますが、あんまりそういう複雑なメディアクエリ書く機会もなく、これなら別に置き換える意味も薄いなーと 😇

window.matchMedia をちゃんと使った方法

先日とある OSS の issue を見ているときに以下のようなwindow.matchMediaの使い方を見つけました 💡

window.matchMediaをちゃんと使った方法
const mediaQueryList = window.matchMedia("(max-width:767px)");

/**
 * イベントリスナー
 */
const listener = (event) => {
  // リサイズ時に行う処理
  if (event.matches) {
    // 768px以上
    console.log('PC用ブレークポイント用処理');
  } else {
    // 768px未満
    console.log('SP用ブレークポイント用処理');
  }
};

// リスナー登録
// mediaQueryList.addListener(listener); // @deprecated
mediaQueryList.addEventListener("change", listener);

// 初期化処理
listener(mediaQueryList);

listener 関数が実行されるのは、ブレークポイントが切り替わったタイミングのだけなので、
resize の監視と比べて無駄に listener 関数が実行されなくなります 🤗🤗🤗

この使い方が MDN のサンプルに載っていないのかなと思っていたらmatchMediaの戻り値のMediaQueryListのほうに書いてありました。。。
そこまでは、なかなか見ない...

GitHubで編集を提案

Discussion

mediaQueryList.addListenerが非推奨なので、以下のように書き換えた方がよさそうです。

- mediaQueryList.addListener(listener);
+ mediaQueryList.addEventListener("change", listener);

@hayato07
ありがとうございます。修正いたしました。

ログインするとコメントできます