Reactjs 的媒体查询语法

Posted

技术标签:

【中文标题】Reactjs 的媒体查询语法【英文标题】:Media query syntax for Reactjs 【发布时间】:2019-06-26 17:56:37 【问题描述】:

如何在 Reactjs 中进行以下 CSS 媒体查询?

.heading 
  text-align: right;
  /* media queries */
  @media (max-width: 767px) 
    text-align: center;
  
  @media (max-width: 400px) 
    text-align: left;
  

我尝试了以下方法,但它会引发语法错误并且无法编译。

heading: 
  textAlign: 'right',
  @media (maxWidth: '767px') 
    textAlign: 'center';
  
  @media (maxWidth: '400px') 
    textAlign: 'left';
  

【问题讨论】:

你好,看我的回答。 【参考方案1】:

事实证明第二个答案非常有用,但是,它只是类组件中的示例,但是将其应用于功能组件通常很困难或很麻烦,而且由于有时将功能组件转换为有问题一类,这里我使用 Hooks

留下示例
import React,  useState, useEffect  from 'react';

const App = () => 
  const [matches, setMatches] = useState(
    window.matchMedia("(min-width: 768px)").matches
  )

  useEffect(() => 
    window
    .matchMedia("(min-width: 768px)")
    .addEventListener('change', e => setMatches( e.matches ));
  , []);

  return (
    <div >
      matches && (<h1>Big Screen</h1>)
      !matches && (<h3>Small Screen</h3>)
    </div>
  );


export default App;

【讨论】:

请注意addListener 是deprecated。建议使用addEventListener 代替:window.matchMedia('(min-width: 768px)').addEventListener('change', e =&gt; setMatches(e.matches))【参考方案2】:

可以在 React 中进行媒体查询:

import React,  Component  from 'react';

class App extends Component 
  constructor(props) 
    super(props)
    this.state =  matches: window.matchMedia("(min-width: 768px)").matches ;
  

  componentDidMount() 
    const handler = e => this.setState(matches: e.matches);
    window.matchMedia("(min-width: 768px)").addEventListener('change', handler);
  
  render() 
    return (
      <div >
      this.state.matches && (<h1>Big Screen</h1>)
      !this.state.matches && (<h3>Small Screen</h3>)
      </div>
    );
  


export default App;

https://stackblitz.com/edit/react-cu8xqj?file=src/App.js


09-10-2021 编辑:将 addListener 替换为 addEventListener,因为前者是 deprecated。感谢 John Galt 通过发表评论告知我们。

【讨论】:

你好@ferit,我说得对吗..我们必须创建不同的组件来处理大屏幕和小屏幕?所以我拥有的每个屏幕都需要为大屏幕和小屏幕创建? 是的,我明白。我的问题是,为了解决不同的屏幕尺寸,我是否应该根据屏幕尺寸创建不同的视图和渲染? @TommyLeong 那是响应式设计。您不能有 50 个屏幕,但可能最多需要 5 个不同的布局。无论 React 和这个答案如何,您都必须分别定义它们以获得响应式设计。 请注意addListener 是deprecated。建议使用addEventListener 代替:window.matchMedia('(min-width: 768px)').addEventListener('change', e =&gt; e.matches) 您可以通过消除handler 来进一步调整此功能,结果将是:window.matchMedia('(min-width: 768px)').addEventListener('change', (e) =&gt; this.setState( matches: e.matches ))【参考方案3】:

在reactjs项目中另一种编写媒体查询的方式:

style.js 文件:

root: 
 background: "white",

 "@media (max-width: 1920px)": 
   background: "red",
 

style.css 文件:

.root: 
 background: "white";

 @media (max-width: 1920px) 
   background: "red";
 

谢谢

【讨论】:

如果使用材质 UI 试试这个:material-ui.com/customization/breakpoints【参考方案4】:

aphrodite 可以帮忙。

这是example:

import React from "react";
import  StyleSheet, css  from "aphrodite";

import "./style.css";

const styles = StyleSheet.create(
  heading: 
    textAlign: "right",
    backgroundColor: "red",
    "@media (max-width: 767px)": 
      textAlign: "center",
      backgroundColor: "green"
    ,
    "@media (max-width: 767px)": 
      textAlign: "center",
      backgroundColor: "blue"
    
  
);

export default function App() 
  return (
    <div className=css(styles.heading)>
      <h1>Hello aphrodite!</h1>
    </div>
  );

【讨论】:

【参考方案5】:

如果你习惯使用 css,你可以使用 styled-components。它看起来像这样。

import React from 'react';
import Styled from "styled-components";

function YourComponent() 

    const heading = Styled.h1`
        Text-align:right;

            @media (max-width: 767px) 
                text-align: center;
            
            @media (max-width: 400px) 
                text-align: left;
            
    `;

   return(
        <>
           <heading>This is my heading</heading>
        </>
    )

如果你需要做很多样式,你可以在另一个 js 文件中做你的样式,并根据需要导入每个样式。如果您这样做,请不要忘记导出您的样式。

【讨论】:

【参考方案6】:

您不能内联设置媒体查询。您需要创建一个单独的 CSS 样式表,然后导入该样式表。

例如,以下代码将放入一个新的styles.css 文件中。

.heading 
  text-align: right;
  /* media queries */
  @media (max-width: 767px) 
    text-align: center;
  
  @media (max-width: 400px) 
    text-align: left;
  

然后,您可以将新的 CSS 样式文件导入您的 react 文件。例如,您可以将 import './styles.css' 添加到您的 App.jsx 文件的顶部(假设它们都在根级别),或者您可以将其直接导入到特定的 react 组件文件中。

【讨论】:

你好,这不是真的,看我的回答。 整洁。不错的更新。不过,没有必要否决我的答案。这是通过 web api,我的意思是你不能使用内联媒体查询。这仍然是正确的。 你是对的,我的解决方案也不是内联的,所以没有办法进行内联查询。但是您也错了,因为您的回答意味着无法在 React 中进行媒体查询。这就是我投反对票的原因。 谁说的里面有什么?不知道你说的里面是什么意思。这个问题没有具体说明“内部”。上面的方法是我在我的反应项目中使用媒体查询的方式。现在开始变得微不足道了。我认为您的评论是对答案的一个很好的补充,但是标记其他做同样事情的正确方法会适得其反。 也许我认为它应该在里面。好的。请对您的答案进行细微的更改,以便我可以恢复我的反对票。【参考方案7】:

在我的情况下,我使用自定义挂钩为我生成一些断点值:

import  useMediaQuery  from 'react-responsive';

export const useBreakpoints = () => 
  const isMobileSmall = useMediaQuery( query: '(max-width: 325px)' );
  const isMobileMid = useMediaQuery( query: '(max-width: 375px)' );
  const isMobileFloor = useMediaQuery( query: '(max-width: 425px)' );

  const isTabletFloor = useMediaQuery( query: '(max-width: 426px)' );
  const isTabletMid = useMediaQuery( query: '(max-width: 768px)' );
  const isTabletCeil = useMediaQuery( query: '(max-width: 1024px)' );

  const isLaptopFloor = useMediaQuery( query: '(max-width: 1025px)' );
  const isLaptopCeil = useMediaQuery( query: '(max-width: 1440px)' );

  const isXHDFloor = useMediaQuery( query: '(max-width: 1441px)' );
  const isXHDCeil = useMediaQuery( query: '(max-width: 4096px)' );

  return 
    isMobileSmall,
    isMobileMid,
    isMobileFloor,
    isTabletFloor,
    isTabletMid,
    isTabletCeil,
    isLaptopFloor,
    isLaptopCeil,
    isXHDFloor,
    isXHDCeil,
  ;
;

我在 useMemo 内部的组件中调用它,这是不正确的 :)

所以我把它放在useMemo 之外,它就像魅力一样!

基本上我要指出的是避免使用嵌套的钩子调用!

【讨论】:

【参考方案8】:

还有一种方法可以通过对 ex 使用布尔值来包含媒体查询。

<div style=window.innerWidth > 768 ? '800px' : '400px'/>

这很好地解决了问题

【讨论】:

那不会使其响应。只有在刷新之后。【参考方案9】:

如果你有特殊情况,当你需要在你的 react 应用程序中获取媒体查询结果时(例如,你想在移动版本中显示一些组件),你可以使用像 react-responsive 或 react-media-hook 这样的 helpers。

【讨论】:

以上是关于Reactjs 的媒体查询语法的主要内容,如果未能解决你的问题,请参考以下文章

网站开发进阶(六十八)CSS3媒体查询@media

媒体查询

媒体查询分组而不是匹配的多个分散的媒体查询

0080 媒体查询media引入资源

媒体查询详解

详解css媒体查询