React应用中,是否有更好的方法根据屏幕大小改变样式?

3
我在我的React应用中使用Material UI,并且我正在使用mui的useMediaQuery和useTheme。这是我现在拥有的代码。是否有更好的方法来优化较少的代码?这两个代码之间只有很少的样式变化。
const MainPage = () => {
    const theme = useTheme();
    const isMatch = useMediaQuery(theme.breakpoints.down('md'))
    return (
        <div className='mainPage'>
            {
                isMatch ? (
                    <>
                        <Box sx={{ display: "flex", justifyContent: "center", alignContent: "center", flexDirection: "column", padding: "60px 10px 10px 10px" }}>
                            <Box component="img" src={LandingImage} sx={{ width: "100%" }} />
                            <Box sx={{ paddingTop: 8 }}>
                                <Typography sx={{ fontSize: 26, fontWeight: "bold", fontFamily: "sans-serif", textAlign: "center", paddingBottom: 5 }}>About us</Typography>
                            </Box>
                        </Box>
                    </>
                ) : (
                    <>
                        <Box sx={{ display: "flex", justifyContent: "center", alignContent: "center", flexDirection: "row", paddingTop: 20 }}>
                            <Box component="img" src={LandingImage} />
                            <Box sx={{ width: 700, paddingTop: 8 }}>
                                <Typography sx={{ fontSize: 30, fontWeight: "bold", fontFamily: "sans-serif", textAlign: "center", paddingBottom: 5 }}>About us</Typography>
                            </Box>
                        </Box>
                    </>
                )}
        </div>
    )
}
4个回答

7

实际上没有必要这样做媒体查询,因为如果需要,sx属性可以提供每个断点的自定义。

例如,注意第一个Box组件上的flexDirection样式。在达到md断点之前,所有内容都是column,然后变成row

const MainPage = () => {
  const theme = useTheme();
  return (
    <div className='mainPage'>
      <Box sx={{ 
        display: "flex", 
        justifyContent: "center", 
        alignContent: "center", 
        flexDirection: { xs: "column", md: "row" },
        padding: { xs: "60px 10px 10px 10px", md: "20px 0 0 0" } 
      }}>
        <Box 
          component="img" 
          src={LandingImage} 
          sx={{ 
            width: { xs: "100%", md: 'unset' }
        }}/>
        <Box sx={{ 
          paddingTop: 8,
          width: { md: 700 }
        }}>
          <Typography 
            sx={{ 
              fontSize: { xs: 26, md: 30 }, 
              fontWeight: "bold", 
              fontFamily: "sans-serif", 
              textAlign: "center", 
              paddingBottom: 5 
          }}>
            About us
          </Typography>
        </Box>
      </Box>
    </div>
  )
}

https://mui.com/system/basics/#responsive-values


4

由于移动端和桌面端的JSX结构相同,您可以删除其中一个JSX模板,构建一个变量来存储基于isMatch的组件配置,然后将此变量传递到组件模板中。


const MainPage = () => {
    const theme = useTheme();
    const isMatch = useMediaQuery(theme.breakpoints.down('md'))

    // Subset of props, to illustrate the idea.
    const config = isMatch ? {fontSize: 26} : {fontSize: 30};

    // Here only root <Box/> is configured, but you can configure all the nested components the same way.
    return (
        <div className='mainPage'>
          <Box sx={config}>[...]</Box>
        </div>
    )
}

(与嵌套在<Box/>内的组件相同-思路是一样的-声明一些基于您的状态的变量,并将它们传递给JSX声明)

我喜欢你的方式,因为它可以在多个组件中使用。 - Jake
附注:我不是MUI框架的专家(实际上以前从未使用过)。也许在这个特定的工具中,有更好的模式来处理响应式断点。 - Piotr Szyma

0

Mui具有断点的速记语法,您可以在此处进行检查。

因此,例如,您的代码也将与以下内容一起使用:

const MainPage = () => {
  return (
    <div className="mainPage">
      <Box
        sx={{
          display: "flex",
          justifyContent: "center",
          alignContent: "center",
          flexDirection: ["column", "column", "row"],
          paddingTop: ["60px 10px 10px 10px", "60px 10px 10px 10px", 20]
        }}
      >
        <Box component="img" />
        <Box sx={{ width: ["unset", "unset", 700], paddingTop: 8 }}>
          <Typography
            sx={{
              fontSize: [26, 26, 30],
              fontWeight: "bold",
              fontFamily: "sans-serif",
              textAlign: "center",
              paddingBottom: 5
            }}
          >
            About us
          </Typography>
        </Box>
      </Box>
    </div>
  );
};    

在上面的例子中,我使用断点作为数组,mui文档如下所示:

第二个选项是将您的断点定义为一个数组,从最小的断点到最大的断点。

因此,想象一下数组位置将是:[xs,sm,md,lg,xl],而断点等同于theme.breakpoints.up
另一种方法是将Breakpoints用作对象: 简单的例子
<Box
   sx={{
      width: {
         xs: 100, // theme.breakpoints.up('xs')
         sm: 200, // theme.breakpoints.up('sm')
         md: 300, // theme.breakpoints.up('md')
         lg: 400, // theme.breakpoints.up('lg')
         xl: 500, // theme.breakpoints.up('xl')
      },
   }}
>

-1
有几种选择。第一种是在JavaScript中创建样式对象,可以像正常的JavaScript一样进行交互。您已经在行内执行了这个操作,但如果我们在上面的代码中执行它,就可以使它变得动态化。
const myOuterBoxStyle = {
  display: "flex", 
  justifyContent: "center", 
  alignContent: "center",
  flexDirection: "row",
  paddingTop: 20
}
if (isMatch) {
  myOuterBoxStyle.flexDirection = "column";
  myOuterBoxStyle.paddingTop = undefined;
  myOuterBoxStyle.padding = "60px 10px 10px 10px";
}

一旦您完成了所有需要的动态样式,您可以为组件进行单个返回并简单地放置。

<Box sx={{myOuterBoxStyle}}>

另一个选项是创建一个单独的CSS样式表并导入它,然后使用类。类似于:
.outer-box {
display: "flex";
justify-content: "center";
align-content: "center";
}

.is-match {
flex-direction: "column";
padding: "60px 10px 10px 10px"
}

然后你可以根据需要添加is-match类或者is-not-match类。

最后一个选项是使用第三方包,它可以为您完成大部分工作,例如Tailwind


如果您只想更改一个组件的样式,那么这可以与if语句一起使用。 - Jake
样式对象可以作为props传递,甚至可以作为上下文传递,但您还可以通过在App.js或index.js上创建CSS表格来进行更通用的样式设置。请检查我的编辑,以获取我提到但忘记放置的其他选项。 - RadicalTurnip

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接