我试图实现类似于YouTube在其网站上所做的事情,那就是:
100d 1xx 1c 1d 1x的字符串
基本上,YT(似乎要做的)是根据容器大小增加/减少网格计数,基于抽屉是否打开/关闭。
底线是,我的代码没有反映布局的变化(我怀疑MUI监听的是窗口的大小而不是父窗口的大小)。
版本:
“@mui/material”:“^5.15.0”,“next”:“^14.0.4”,“react”:“18.2.0”,
谢谢
我试过使用MUI + NextJS做类似的事情,但它不起作用。
相关片段:
import { Box, Container } from '@mui/material'
import Header from '../components/Layout/Header'
import { ServerAuthProvider } from '../../auth/server-auth-provider'
export default function Layout(props: {
children: React.ReactNode,
body: React.ReactNode,
filters: React.ReactNode,
}) {
return (
<ServerAuthProvider>
<Header maxWidth={false}>
<Container maxWidth={false}>
<Box ml={2} mt={10}>
{props.filters}
{props.body}
{props.children}
</Box>
</Container>
</Header>
</ServerAuthProvider>
)
}
字符串
身体(相关部分)
<Box sx={{ mt: 2, mb: 2, ml: -1, mr: -1 }}>
<Unstable_Grid2 container spacing={2}>
{events?.map((event: EventSummary) => (
<Unstable_Grid2 xs={12} sm={6} md={6} lg={4} xl={3} xxl={12 / 5} key={event.id + event.starts_at}>
<EventCard event={event} />
</Unstable_Grid2>
))}
</Unstable_Grid2 >
</Box >
const drawerWidth = 240;
const openedMixin = (theme: Theme): CSSObject => ({
width: drawerWidth,
transition: theme.transitions.create('width', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen,
}),
overflowX: 'hidden',
border: 'none',
borderWidth: 0,
});
const closedMixin = (theme: Theme): CSSObject => ({
transition: theme.transitions.create('width', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
overflowX: 'hidden',
border: 'none',
borderWidth: 0,
width: `calc(${theme.spacing(7)} + 1px)`,
[theme.breakpoints.up('sm')]: {
width: `calc(${theme.spacing(8)} + 1px)`,
},
});
const DrawerHeader = styled('div')(({ theme }) => ({
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-end',
padding: theme.spacing(0, 1),
// necessary for content to be below app bar
...theme.mixins.toolbar,
}));
const Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => prop !== 'open' })(
({ theme, open }) => ({
width: drawerWidth,
flexShrink: 0,
whiteSpace: 'nowrap',
boxSizing: 'unset',
...(open && {
...openedMixin(theme),
'& .MuiDrawer-paper': openedMixin(theme),
}),
...(!open && {
...closedMixin(theme),
'& .MuiDrawer-paper': closedMixin(theme),
}),
}),
);
const Main = styled('main', { shouldForwardProp: (prop) => prop !== 'open' })<{
open?: boolean;
}>(({ theme, open }) => ({
flexGrow: 1,
// padding: theme.spacing(3),
// transition: theme.transitions.create('margin', {
// easing: theme.transitions.easing.sharp,
// duration: theme.transitions.duration.leavingScreen,
// }),
// width: `calc(100% - ${drawerWidth}px)`,
...(open && {
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen,
}),
marginLeft: 0,
overflow: 'auto'
}),
}));
export default function PrimaryHeader({ maxWidth, children }: { maxWidth?: false | undefined, children?: ReactNode }) {
const [anchorElNav, setAnchorElNav] = React.useState<null | HTMLElement>(null);
const [open, setOpen] = useState(false)
const { user } = useAuth();
const { getFirebaseAuth } = useFirebaseAuth()
const router = useRouter()
const theme = useTheme()
const isXl = useMediaQuery(theme.breakpoints.only('xl'))
const isMd = useMediaQuery(theme.breakpoints.up('md'))
const logout = async () => {
const auth = getFirebaseAuth()
await signOut(auth)
await fetch('/api/logout')
window.location.reload()
}
const loggedOptions = [{ title: 'Logout', callback: logout }]
const notLoggedOptions = [{ title: 'Entrar', callback: () => router.push('/login') }]
return (
<Box sx={{ display: 'flex' }}>
<CssBaseline />
<AppBar position="fixed" sx={{ bgcolor: 'white', zIndex: theme.zIndex.drawer + 1, }} elevation={0}>
<Container disableGutters maxWidth={maxWidth}>
<Toolbar>
{!!children && <IconButton
color="inherit"
aria-label="open drawer"
onClick={() => { setOpen((prev) => !prev) }}
edge="start"
sx={{ mr: 2 }}
>
<MenuIcon sx={{ color: 'black' }} />
</IconButton>}
</Toolbar>
</Container>
</AppBar>
{!!children && <>
<Drawer
variant="permanent"
open={open}
>
<DrawerHeader />
<List>
{['Inbox', 'Starred', 'Send email', 'Drafts'].map((text, index) => (
<ListItem key={text} disablePadding sx={{ display: 'block' }}>
<ListItemButton
sx={{
minHeight: 48,
justifyContent: open ? 'initial' : 'center',
px: 2.5,
}}
>
<ListItemIcon
sx={{
minWidth: 0,
mr: open ? 3 : 'auto',
justifyContent: 'center',
}}
>
{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}
</ListItemIcon>
<ListItemText primary={text} sx={{ opacity: open ? 1 : 0 }} />
</ListItemButton>
</ListItem>
))}
</List>
</Drawer>
<Main open={open}><Container maxWidth={maxWidth}>{children}</Container></Main>
</>}
</Box>
)
}
的数据
1条答案
按热度按时间oyjwcjzk1#
你是对的,断点是基于视口宽度,而不是当前容器宽度。
但你所寻找的可以使用基本的CSS网格实现:
点击侧边栏进行切换。
关键在于
型
...它试图在可用宽度内容纳尽可能多的
150px
列。任何额外的宽度然后在列之间平均分配。将
150px
更改为对您的情况有意义的任何内容。其他内容都不是特别相关;我添加它是为了使示例看起来更像一个 “布局”。
如果您不希望列具有可变宽度,而是希望将额外的空间分布在两侧,请使用:用途:
型
演示:
x
同样,将
150px
更改为适合您需要的任何值。