在现代前端开发中,响应式设计是至关重要的。为了实现这一点,我们经常使用 CSS media queries。但有时,我们需要在 JavaScript 中访问这些查询的结果,以便更好地控制组件的行为。本文将介绍如何在 Vue 和 React 中动态响应 CSS media queries。

1. 为什么需要在 JavaScript 中访问 Media Queries?

虽然 CSS media queries 对于应用样式非常有用,但有时我们需要更多的控制。例如,我们可能想在移动设备上显示一个组件,而在桌面上隐藏它。或者,我们可能想根据屏幕大小更改组件的行为。

2. 使用 window.matchMedia

window.matchMedia 是一个 JavaScript 方法,它返回一个 MediaQueryList 对象。这个对象表示一个媒体查询,它可以用来检测文档是否匹配该媒体查询。

const isMobile = window.matchMedia('(max-width: 768px)').matches;

3. 动态响应 Media Queries

Vue自定义组合式函数示例

<script>
import { ref, onMounted, onUnmounted } from 'vue';

// 自定义组合式函数
function useMediaQuery(query) {
  const matches = ref(window.matchMedia(query).matches);

  const handleResize = () => {
    matches.value = window.matchMedia(query).matches;
  };

  onMounted(() => {
    window.addEventListener('resize', handleResize);
  });

  onUnmounted(() => {
    window.removeEventListener('resize', handleResize);
  });

  return matches;
}

export default {
  setup() {
    const isMobile = useMediaQuery('(max-width: 768px)');

    return {
      isMobile
    };
  }
}
</script>

<template>
  <div v-if="isMobile">Mobile View</div>
  <div v-else>Desktop View</div>
</template>

React自定义Hook示例

自定义Hook,参数为自定义媒体查询字符串:

import React, { useState, useEffect } from 'react';

// 自定义 Hook
function useMediaQuery(query) {
  const [matches, setMatches] = useState(window.matchMedia(query).matches);

  useEffect(() => {
    const mediaQueryList = window.matchMedia(query);
    const handleResize = () => {
      setMatches(mediaQueryList.matches);
    };

    mediaQueryList.addListener(handleResize);
    return () => {
      mediaQueryList.removeListener(handleResize);
    };
  }, [query]);

  return matches;
}

// 使用自定义 Hook 的组件
function ResponsiveComponent() {
  const isMobile = useMediaQuery('(max-width: 768px)');

  return isMobile ? <div>Mobile View</div> : <div>Desktop View</div>;
}

结论

响应 CSS media queries 不仅仅是一个样式问题。有时,我们需要在 JavaScript 中访问这些查询的结果,以便更好地控制组件的行为。无论你是使用 Vue 还是 React,都可以轻松地实现这一功能,从而为用户提供更好的体验。


A Student on the way to full stack of Web3.