如何垂直分隔 Material UI 网格纸组件?
How to vertically separate Material UI Gridded Paper components?
目标组件没有像我希望的那样 spaced。这是他们目前的样子。
到目前为止,我已尝试将纸张选择器显示设置为 flex。我还尝试增加不同 Grid 组件的间距属性。增加 space 只会使填充扩展。
我希望它们 space 彼此垂直分开而不是重叠。我怎样才能响应地完成这个?我希望它看起来像下图,其中红色框是目标组件,黑色框代表网页。
import React, { useEffect } from "react";
import Moment from "react-moment";
import PropTypes from "prop-types";
import { Link } from "react-router-dom";
import { connect } from "react-redux";
import { getGoals } from "../../actions/goal";
import Spinner from "../layout/Spinner";
import Navbar from "../dashboard/Navbar";
import ThumbUpAltIcon from "@material-ui/icons/ThumbUpAlt";
import ThumbDownAltIcon from "@material-ui/icons/ThumbDownAlt";
import ChatIcon from "@material-ui/icons/Chat";
import DeleteIcon from "@material-ui/icons/Delete";
import DoneIcon from "@material-ui/icons/Done";
import {
Typography,
Container,
CssBaseline,
makeStyles,
Grid,
Avatar,
Paper
} from "@material-ui/core";
const useStyles = makeStyles(theme => ({
paper: {
height: "auto"
},
actionButtons: {
marginTop: "3vh"
},
profileHeader: {
textAlign: "center",
marginBottom: 20
},
avatar: {
width: theme.spacing(7),
height: theme.spacing(7)
}
}));
const Goals = ({ getGoals, auth, goal: { goals, user, loading } }) => {
useEffect(() => {
getGoals();
}, [getGoals]);
const classes = useStyles();
return loading ? (
<>
<Navbar />
<Container component="main" maxWidth="xs">
<CssBaseline />
<div className={classes.paper}>
<Spinner />
</div>
</Container>
</>
) : (
<>
<CssBaseline />
<Navbar />
<Container>
<Typography variant="h2" className={classes.profileHeader}>
Goals
</Typography>
{/* parent grid */}
<Grid container spacing={4}>
{goals.map(singleGoal => (
<Grid
className={classes.paper}
key={singleGoal._id}
spacing={1}
container
item
direction="row"
alignItems="center"
component={Paper}
>
<Grid
item
container
direction="column"
justify="center"
alignItems="center"
xs={3}
>
<Avatar className={classes.avatar} src={singleGoal.avatar} />
<Typography variant="caption">
{singleGoal.first_name} {singleGoal.last_name}
</Typography>
<Typography variant="caption" className={classes.postedOn}>
Posted on{" "}
<Moment format="MM/DD/YYYY">{singleGoal.date}</Moment>
</Typography>
</Grid>
<Grid container item direction="column" xs={9}>
<Typography variant="body1">{singleGoal.text}</Typography>
<Grid item className={classes.actionButtons}>
<ThumbUpAltIcon />
<ThumbDownAltIcon />
<ChatIcon />
<DoneIcon />
<DeleteIcon />
</Grid>
</Grid>
</Grid>
))}
</Grid>
</Container>
</>
);
};
Goals.propTypes = {
getGoals: PropTypes.func.isRequired,
goal: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
goal: state.goal,
auth: state.auth
});
export default connect(mapStateToProps, { getGoals })(Goals);
垂直使用 <Paper />
并设置间距样式:
import React from "react";
import "./styles.css";
import { makeStyles } from "@material-ui/core/styles";
import Paper from "@material-ui/core/Paper";
const useStyles = makeStyles(theme => ({
root: {
display: "flex",
//flexWrap: 'wrap',
"& > *": {
margin: theme.spacing(1),
width: theme.spacing(46),
height: theme.spacing(16)
},
padding: theme.spacing(5, 5),
height: "100%",
//display: "flex",
flexDirection: "column",
justifyContent: "center"
},
paper: {
//margin: theme.spacing(10),
marginBottom: theme.spacing(5) // Change this line for more spacing
}
}));
export default function SimplePaper() {
const classes = useStyles();
return (
<div className={classes.root}>
<Paper elevation={4} className={classes.paper} />
<Paper elevation={4} className={classes.paper} />
<Paper elevation={4} className={classes.paper} />
</div>
);
}
答案输出:HERE
我已经使用 Grid with Paper 组件(与您的类似)创建了一个响应式布局示例。希望对您有所帮助。
import React from "react";
import "./styles.css";
import { makeStyles } from "@material-ui/core/styles";
import { Avatar, Grid, Paper, Typography } from "@material-ui/core";
const useStyles = makeStyles(theme => ({
root: {
padding: theme.spacing(2)
},
paper: {
minHeight: theme.spacing(10),
padding: theme.spacing(2)
},
avatar: {
marginBottom: theme.spacing(1.5)
},
[theme.breakpoints.down("xs")]: {
description: {
marginTop: theme.spacing(1.5)
}
}
}));
export default function SimplePaper() {
const classes = useStyles();
const users = [
{
name: "Jason",
desc: `Lorem Ipsum is simply dummy text of the printing and typesetting
industry. Lorem Ipsum has been the industry's standard dummy text ever
since the 1500s, when an unknown printer took a galley of type and
scrambled it to make a type specimen book.`
},
{
name: "Jonathan",
desc: `Lorem Ipsum is simply dummy text of the printing and typesetting
industry. Lorem Ipsum has been the industry's standard dummy text ever
since the 1500s, when an unknown printer took a galley of type and
scrambled it to make a type specimen book.`
},
{
name: "Joshua",
desc: `Lorem Ipsum is simply dummy text of the printing and typesetting
industry. Lorem Ipsum has been the industry's standard dummy text ever
since the 1500s, when an unknown printer took a galley of type and
scrambled it to make a type specimen book.`
}
];
const renderPaper = ({ name, desc }) => (
<Grid
className={classes.paper}
component={Paper}
container
alignItems="center"
>
<Grid item xs={12} sm={3} md={2}>
<Grid container direction="column" alignItems="center">
<Avatar className={classes.avatar} />
<Typography variant="subtitle2">{name}</Typography>
</Grid>
</Grid>
<Grid item xs={12} sm={9} md={10}>
<Typography
variant="body1"
align="left"
className={classes.description}
>
{desc}
</Typography>
</Grid>
</Grid>
);
return (
<Grid className={classes.root} container direction="column" spacing={4}>
{users.map(user => (
<Grid item>{renderPaper(user)}</Grid>
))}
</Grid>
);
}
工作演示:https://codesandbox.io/s/broken-monad-jv6pv?fontsize=14&hidenavigation=1&theme=dark
目标组件没有像我希望的那样 spaced。这是他们目前的样子。
到目前为止,我已尝试将纸张选择器显示设置为 flex。我还尝试增加不同 Grid 组件的间距属性。增加 space 只会使填充扩展。
我希望它们 space 彼此垂直分开而不是重叠。我怎样才能响应地完成这个?我希望它看起来像下图,其中红色框是目标组件,黑色框代表网页。
import React, { useEffect } from "react";
import Moment from "react-moment";
import PropTypes from "prop-types";
import { Link } from "react-router-dom";
import { connect } from "react-redux";
import { getGoals } from "../../actions/goal";
import Spinner from "../layout/Spinner";
import Navbar from "../dashboard/Navbar";
import ThumbUpAltIcon from "@material-ui/icons/ThumbUpAlt";
import ThumbDownAltIcon from "@material-ui/icons/ThumbDownAlt";
import ChatIcon from "@material-ui/icons/Chat";
import DeleteIcon from "@material-ui/icons/Delete";
import DoneIcon from "@material-ui/icons/Done";
import {
Typography,
Container,
CssBaseline,
makeStyles,
Grid,
Avatar,
Paper
} from "@material-ui/core";
const useStyles = makeStyles(theme => ({
paper: {
height: "auto"
},
actionButtons: {
marginTop: "3vh"
},
profileHeader: {
textAlign: "center",
marginBottom: 20
},
avatar: {
width: theme.spacing(7),
height: theme.spacing(7)
}
}));
const Goals = ({ getGoals, auth, goal: { goals, user, loading } }) => {
useEffect(() => {
getGoals();
}, [getGoals]);
const classes = useStyles();
return loading ? (
<>
<Navbar />
<Container component="main" maxWidth="xs">
<CssBaseline />
<div className={classes.paper}>
<Spinner />
</div>
</Container>
</>
) : (
<>
<CssBaseline />
<Navbar />
<Container>
<Typography variant="h2" className={classes.profileHeader}>
Goals
</Typography>
{/* parent grid */}
<Grid container spacing={4}>
{goals.map(singleGoal => (
<Grid
className={classes.paper}
key={singleGoal._id}
spacing={1}
container
item
direction="row"
alignItems="center"
component={Paper}
>
<Grid
item
container
direction="column"
justify="center"
alignItems="center"
xs={3}
>
<Avatar className={classes.avatar} src={singleGoal.avatar} />
<Typography variant="caption">
{singleGoal.first_name} {singleGoal.last_name}
</Typography>
<Typography variant="caption" className={classes.postedOn}>
Posted on{" "}
<Moment format="MM/DD/YYYY">{singleGoal.date}</Moment>
</Typography>
</Grid>
<Grid container item direction="column" xs={9}>
<Typography variant="body1">{singleGoal.text}</Typography>
<Grid item className={classes.actionButtons}>
<ThumbUpAltIcon />
<ThumbDownAltIcon />
<ChatIcon />
<DoneIcon />
<DeleteIcon />
</Grid>
</Grid>
</Grid>
))}
</Grid>
</Container>
</>
);
};
Goals.propTypes = {
getGoals: PropTypes.func.isRequired,
goal: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
goal: state.goal,
auth: state.auth
});
export default connect(mapStateToProps, { getGoals })(Goals);
垂直使用 <Paper />
并设置间距样式:
import React from "react";
import "./styles.css";
import { makeStyles } from "@material-ui/core/styles";
import Paper from "@material-ui/core/Paper";
const useStyles = makeStyles(theme => ({
root: {
display: "flex",
//flexWrap: 'wrap',
"& > *": {
margin: theme.spacing(1),
width: theme.spacing(46),
height: theme.spacing(16)
},
padding: theme.spacing(5, 5),
height: "100%",
//display: "flex",
flexDirection: "column",
justifyContent: "center"
},
paper: {
//margin: theme.spacing(10),
marginBottom: theme.spacing(5) // Change this line for more spacing
}
}));
export default function SimplePaper() {
const classes = useStyles();
return (
<div className={classes.root}>
<Paper elevation={4} className={classes.paper} />
<Paper elevation={4} className={classes.paper} />
<Paper elevation={4} className={classes.paper} />
</div>
);
}
答案输出:HERE
我已经使用 Grid with Paper 组件(与您的类似)创建了一个响应式布局示例。希望对您有所帮助。
import React from "react";
import "./styles.css";
import { makeStyles } from "@material-ui/core/styles";
import { Avatar, Grid, Paper, Typography } from "@material-ui/core";
const useStyles = makeStyles(theme => ({
root: {
padding: theme.spacing(2)
},
paper: {
minHeight: theme.spacing(10),
padding: theme.spacing(2)
},
avatar: {
marginBottom: theme.spacing(1.5)
},
[theme.breakpoints.down("xs")]: {
description: {
marginTop: theme.spacing(1.5)
}
}
}));
export default function SimplePaper() {
const classes = useStyles();
const users = [
{
name: "Jason",
desc: `Lorem Ipsum is simply dummy text of the printing and typesetting
industry. Lorem Ipsum has been the industry's standard dummy text ever
since the 1500s, when an unknown printer took a galley of type and
scrambled it to make a type specimen book.`
},
{
name: "Jonathan",
desc: `Lorem Ipsum is simply dummy text of the printing and typesetting
industry. Lorem Ipsum has been the industry's standard dummy text ever
since the 1500s, when an unknown printer took a galley of type and
scrambled it to make a type specimen book.`
},
{
name: "Joshua",
desc: `Lorem Ipsum is simply dummy text of the printing and typesetting
industry. Lorem Ipsum has been the industry's standard dummy text ever
since the 1500s, when an unknown printer took a galley of type and
scrambled it to make a type specimen book.`
}
];
const renderPaper = ({ name, desc }) => (
<Grid
className={classes.paper}
component={Paper}
container
alignItems="center"
>
<Grid item xs={12} sm={3} md={2}>
<Grid container direction="column" alignItems="center">
<Avatar className={classes.avatar} />
<Typography variant="subtitle2">{name}</Typography>
</Grid>
</Grid>
<Grid item xs={12} sm={9} md={10}>
<Typography
variant="body1"
align="left"
className={classes.description}
>
{desc}
</Typography>
</Grid>
</Grid>
);
return (
<Grid className={classes.root} container direction="column" spacing={4}>
{users.map(user => (
<Grid item>{renderPaper(user)}</Grid>
))}
</Grid>
);
}
工作演示:https://codesandbox.io/s/broken-monad-jv6pv?fontsize=14&hidenavigation=1&theme=dark