React组件中的可滚动div

时间:2018-07-11 20:43:11

标签: javascript reactjs redux

我要构建一个日历Web应用程序。为此,我需要一个周视图,以显示该周的所有事件。我要参考的是Google日历,因为该设计是现代的,而且结构非常好。所以对于应用程序,我将React和redux用作状态管理。但是我似乎遇到了一个困扰我一段时间的问题。使滚动条可以用作Google日历周视图中的滚动条(即垂直滚动条)。

重要组成部分: 最低级别的组件(名称:身体)

import React from 'react';
import { withStyles, withWidth, Typography } from '@material-ui/core';
import moment from 'moment';
import {
    weekHeadMaxWidthXl,
    weekHeadMinWidthXl,
    weekHeadMaxWidthLg,
    weekHeadMinWidthLg,
    weekHeadMaxWidthMd,
    weekHeadMinWidthMd,
    weekHeadMaxWidthSm,
    weekHeadMinWidthSm,
    weekHeadMaxWidthXs,
    weekHeadMinWidthXs,
    weekHeadHightXl
} from '../../../util/dimension';
const style = theme => ({
    bodyContainer: {
        display: "flex",
        flexDirection: "row",
        overflow: "auto",
        width: "100%",
    },
    hourContainer: {
        display: "flex",
        flexDirection: "column",
        marginTop: 1,
        [theme.breakpoints.only('xl')]: {
            maxWidth: weekHeadMaxWidthXl,
            minWidth: weekHeadMinWidthXl,
            width: "100%",
        },
        [theme.breakpoints.only('lg')]: {
            maxWidth: weekHeadMaxWidthLg,
            minWidth: weekHeadMinWidthLg,
            width: "100%",
        },
        [theme.breakpoints.only('md')]: {
            maxWidth: weekHeadMaxWidthMd,
            minWidth: weekHeadMinWidthMd,
            width: "100%",
        },
        [theme.breakpoints.only('sm')]: {
            maxWidth: weekHeadMaxWidthSm,
            minWidth: weekHeadMinWidthSm,
            width: "100%",
            backgroundColor: "#"
        },
        [theme.breakpoints.only('xs')]: {
            maxWidth: weekHeadMaxWidthXs,
            minWidth: weekHeadMinWidthXs,
            width: "100%",
        },

    },
    hour: {
        [theme.breakpoints.only('xl')]: {
            maxHeight: "50px",
            height: "46px",
            minHeight: "44px",
        },
        [theme.breakpoints.only('lg')]: {
            maxHeight: "50px",
            height: "46px",
            minHeight: "44px",
        },
        [theme.breakpoints.only('md')]: {
            maxHeight: "50px",
            height: "46px",
            minHeight: "44px",
        },
        [theme.breakpoints.only('sm')]: {
            maxHeight: "50px",
            height: "46px",
            minHeight: "44px",
        },
        borderBottom: "solid 1px #e7e7e7",
        borderLeft: "solid 1px #e7e7e7",
        backgroundColor: "#FFF"
    },
    offset: {
        display: "flex",
        justifyContent: "center",
        paddingTop: 10,
        backgroundColor: "#FFF",
        borderBottom: "solid 1px #e7e7e7",
        borderTop: "solid 1px #e7e7e7",
        [theme.breakpoints.only('xl')]: {
            maxWidth: 55,
            minWidth: 50,
            width: 53,
        },
        [theme.breakpoints.only('lg')]: {
            maxWidth: 53,
            minWidth: 47,
            width: 50,
        },
        [theme.breakpoints.only('md')]: {
            maxWidth: 50,
            minWidth: 43,
            width: 47,
        },
        [theme.breakpoints.only('sm')]: {
            maxWidth: 47,
            minWidth: 38,
            width: 43,

        },
        [theme.breakpoints.only('xs')]: {
            maxWidth: 47,
            minWidth: 43,
            width: 38,
        },
    },
});

const body = props => {
    const { classes } = props;
    let days = [];
    const getHours = () => {
            let hours = [];
            for (let i = 0; i < 24; i++) {
                hours.push(<div key={"hours " + i} className={classes.hour}>
                    <Typography> {i} </Typography>
                </div>)
            }
            return hours
        }
    days.push(<div key="offset" className={classes.offset}></div>)
    for (let j = 0; j < 7; j++) {
        days.push(<div key={"days " + j} className={classes.hourContainer}>
        {getHours()}
        </div>)
    }

    return (<div className={classes.bodyContainer}>
        {days}
    </div>);
}

export default withWidth()(withStyles(style)(body));

组件实现主体。 (名称:日历)

import React from 'react';
import { withStyles, Typography, TableCell } from '@material-ui/core';
import withWidth, { isWidthUp } from '@material-ui/core/withWidth';
import { connect } from 'react-redux'
import { changeWindowSizeAction } from '../../redux/actions/settingsActions';
import Month from './views/month/month';
import MonthOffset from './views/month/offset';
import WeekHead from './views/week/head';
import WeekBody from './views/week/body';


const styles = theme => ({
    week: {
        height: "100vh",
    },
    weekBody: {
        height: "100vh",
        overflowY: "auto"
    }
});


class Calendar extends React.Component {
    getFullDayBookings = bookings => {
        return bookings.filter(B => B.allDay);
    }
    generateComponent = (variant, props) => {
        switch (variant) {
            case "month":
                return <Month onDayClick={props.onDayClick} onBookingClick={props.onBookingClick} dateNr={props.nr} day={props.day} bookings={this.formatBookings()} />
            case "week":
                return this.generateWeek()
            case "day":
                return null;
            case "agenda":
                return null;
            case "offset":
                return <MonthOffset dateNr={props.nr} variant="month" />
            default:
                return (
                    <TableCell className={props.classes.monthCell}>

                    </TableCell>
                );
        }

    }
    generateWeek = () => {
        return (<div className={this.props.classes.week}>
            <WeekHead bookings={this.formatBookings().filter(E => E.allDay)} />
            <div className={this.props.classes.weekBody}>
                <WeekBody />
            </div>
        </div>)
    }
    formatBookings = () => {
        if (this.props.bookings.length > 0) {
            return this.filterBookings(this.props.bookings, this.props.bookingFilter)
        } else {
            return [];
        }

    }
    filterBookings = (bookings, filter) => {
        if (bookings.length > 0) {
            let notToRender = Object.keys(filter).filter(F => {
                if (!filter[F]) {
                    return F;
                }
            });
            return bookings.filter(E => {
                if (notToRender.length > 0) {
                    if (notToRender.indexOf(E.room) === -1) {
                        return E
                    }
                } else {
                    return E;
                }
            });
        } else {
            return []
        }
    }
    render() {
        return (this.generateComponent(this.props.variant, this.props))
    }

}

const mapDispatchToProps = dispatch => {
    return {
        changeWindowSize: wSize => (dispatch(changeWindowSizeAction(wSize)))
    }
}
const mapStateToProps = state => {
    return {
        windowSize: state.settings.windowSize,
    }
}

export default withWidth()(withStyles(styles)(connect(mapStateToProps, mapDispatchToProps)(Calendar)));

实施日历的组件(名称:星期)

import React from 'react';
import { connect } from 'react-redux';
import Calendar from '../components/calendar/Calendar';
import { withStyles, Typography } from '@material-ui/core';
import moment from 'moment';


const styles = theme => ({

});


const testEvents = [
    { "title": "Test - NotAllDay", "id": 1, "room": "office" },
    { "title": "Test - NotAllDay", "id": 2, "room": "office" },
    { "title": "Test - Cafe", "id": 3, "room": "cafe", "allDay": true, "startDate": moment(), "endDate": moment().add(2, "days") },
    { "title": "Test - NotAllDay", "id": 11, "room": "office" }]



class Week extends React.Component {
    render(){
        return <Calendar variant="week" bookings={testEvents} bookingFilter={this.props.filter}/>
    }
}


const mapStateToPops = state => ({
    currentDate: state.settings.calendarState,
    filter: state.settings.roomsRender,
});

const mapDispatchToProps = dispatch => ({

});

export default withStyles(styles)(connect(mapStateToPops, mapDispatchToProps)(Week));

最后一个组件实施周

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { withStyles } from '@material-ui/core/styles/';
import classNames from 'classnames';
import PropTypes from 'prop-types'; 
import Banner from '../containers/Banner';
import Sidebar from '../containers/Sidebar';
import Month from '../containers/Month';
import Week from '../containers/Week';
import './styles.css';
const styles = theme => ({
    DisplayContainer: {
        flex: 1,
        height: "100vh"
    },
    content: {
        height: "100%",
        flex: 3,
        flexGrow: 1,
        backgroundColor: theme.palette.background.default,
        transition: theme.transitions.create('margin', {
            easing: theme.transitions.easing.sharp,
            duration: theme.transitions.duration.leavingScreen,
        }),
    },
    'content-left': {
        marginLeft: 0,
    },
    contentShift: {
        transition: theme.transitions.create('margin', {
            easing: theme.transitions.easing.easeOut,
            duration: theme.transitions.duration.enteringScreen,
        }),
    },
    'contentShift-left': {
        marginLeft: 240,
    },
});


class Overview extends Component {
    calendarView = () => {
        switch (this.props.calendarType) {
            case "month":
                return <Month />
            case "week":
                return <Week />
            case "day":
                return <div></div>
            case "agenda":
                return <div></div>
            default:
                return <div></div>
        }
    }
    render() {
        const { classes, theme } = this.props;
        return (
            <div className={classes.DisplayContainer}>
                <div className="Banner">
                    <Banner />
                </div>
                <div>
                    <Sidebar />
                </div>
                <main className={classNames(classes.content, classes[`content-left`], {
                    [classes.contentShift]: this.props.showMenu,
                    [classes[`contentShift-left`]]: this.props.showMenu,
                })}>
                    {this.calendarView()}
                </main>
            </div>
        )
    }
}

Overview.propTypes ={
    classes: PropTypes.object.isRequired,
}

const mapStateToProps = state => {
    return {
        showMenu: state.settings.showMenu,
        calendarType: state.settings.calendarType,
    }
}


export default withStyles(styles)(connect(mapStateToProps)(Overview));

“月”视图可以正常工作。它们有一些错误,但是应用程序很久没有完成。所以,是的,如果有人可以指出我的方向或提供一些内部知识,那太好了!

多谢指教!

1 个答案:

答案 0 :(得分:1)

这是CSS修复程序:

将此CSS添加到您的应用程序中:

html, #root {
   height: 100%
}

.jss2.jss3{
   height: calc(100% - 65px);
}

.jss189 {
    height: calc(100% - 132px);
}