简体   繁体   English

有没有更好的方法来根据反应应用程序的屏幕大小更改样式?

[英]Is there a better way to change style based on screen size on react app?

Im using Material UI on my react app and I'm using useMediaQuery and useTheme from mui.我在我的反应应用程序上使用 Material UI,我正在使用来自 mui 的 useMediaQuery 和 useTheme。 This is the code I have right now.这是我现在拥有的代码。 Is there a better way to optimize less code?有没有更好的方法来优化更少的代码? There are only a few style changes between the 2 codes.两个代码之间只有少数样式更改。

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>
    )
}

As the structure of JSX for mobile / desktop is the same, you could drop one of those two JSX templates, build a variable to store component configuration based on isMatch and pass this variable into component template.由于移动/桌面 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>
    )
}

(Same with components nested inside <Box/> - the idea is the same - declare some variables with value based on your state and pass them to JSX declaration) (与嵌套在<Box/>中的组件相同 - 想法相同 - 根据您的状态声明一些具有值的变量并将它们传递给 JSX 声明)

There really is no need to do a media query like this, as the sx prop provides per-breakpoint customization if you want it.确实不需要像这样进行媒体查询,因为sx属性提供了每个断点的自定义,如果你想要的话。

Notice, for example, the flexDirection styling on the first Box component.例如,请注意第一个 Box 组件上的flexDirection样式。 Everything up to the md breakpoint gets column , then it becomes row .直到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 https://mui.com/system/basics/#responsive-values

There are several options.有几种选择。 The first is to create a style object in javascript, which can be interacted with like normal javascript.首先是在 javascript 中创建一个样式对象,它可以像普通的 javascript 一样进行交互。 You are already doing this in-line, but if we do it in the code above, we can make it dynamic.您已经在线执行此操作,但如果我们在上面的代码中执行此操作,我们可以使其动态化。

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";
}

Once you do all of the dynamic styling you need, you can make a single return for your component and simply put一旦你完成了你需要的所有动态样式,你可以为你的组件做一个单一的回报,然后简单地把

<Box sx={{myOuterBoxStyle}}>

The other option is to make a seperate CSS sheet and import it, and then use classes.另一种选择是制作一个单独的 CSS 表并导入它,然后使用类。 Something like就像是

.outer-box {
display: "flex";
justify-content: "center";
align-content: "center";
}

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

And then you can either add the is-match class or, perhaps, the is-not-match class depending.然后您可以添加is-match类,或者可能添加is-not-match类,具体取决于。

The final option is to use a third-party package that does most of this for you, like Tailwind最后一种选择是使用第三方包,它可以为您完成大部分工作,例如Tailwind

Mui has breakpoints shorthand syntax, as you can check here . Mui 有断点简写语法,你可以在这里查看

So, for example, your code will also work with:因此,例如,您的代码也适用于:

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>
  );
};    

In the example above i use the Breakpoints as an array and mui docs says:在上面的示例中,我使用断点作为数组, mui文档说:

The second option is to define your breakpoints as an array, from the smallest to the largest breakpoint.第二个选项是将断点定义为一个数组,从最小到最大的断点。

So imagine that array positions would be: [xs, sm, md, lg, xl] and the breakpoints are equivalent to theme.breakpoints.up .所以想象数组位置是: [xs, sm, md, lg, xl]并且断点等同于theme.breakpoints.up

Another way to do it is use Breakpoints as an object:另一种方法是使用断点作为对象:

Simple example简单的例子

<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')
      },
   }}
>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM