是否有更好的方法来改变基于屏幕大小的风格在react应用程序?



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

真的没有必要做这样的媒体查询,因为如果您需要的话,sxprop提供了每个断点的自定义。

例如,请注意第一个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

由于移动/桌面的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声明)

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

另一种方法是使用断点作为对象:

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

有几个选项。第一种方法是在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

最新更新