This is the 12th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

TIP 👉 boohoo! Although chu three households can destroy qin, there is no open China! ____ Lu You “Golden Mistake Knife Trip”

preface

Web Component is an area that the front-end world has been very enthusiastic about. To implement it with third-party componentized frameworks, you need to rely on a lot of things in the framework itself. Most of the time we just have a few simple components, not too big, not too many, so in order to keep the components lightweight, Simple, we don’t really want to use a third party framework at this point.

Date picker component

import

import DatePicker from '@/components/DatePicker/DatePicker';
Copy the code

Props

1. onChange
  • Type: func (required)
  • Default value: none
  • Note: Select the callback function after the date, input parameter:
    • {my Moment | Date | String | Number} the value selected Date value (and valueType correspondence)
    • MomentValue momentValue for the Moment value of the date
2. valueType
  • Type: datepicker. VALUE_TYPE
  • Default value: datepicker.value_type.string
  • Description: Date value type
3. value
  • Type: valueType Specifies the type
  • Default value: none
  • Description: Date value
<DatePicker value={'2019-12-12'}
            valueType={DatePicker.VALUE_TYPE.string}
            onChange={this.dateChange} />
Copy the code
<DatePicker value={new Date()}
            valueType={DatePicker.VALUE_TYPE.date}
            onChange={this.dateChange} />
Copy the code
<DatePicker value={1576049926055}
            valueType={DatePicker.VALUE_TYPE.millisecond}
            onChange={this.dateChange} />
Copy the code
<DatePicker value={moment()}
            valueType={DatePicker.VALUE_TYPE.moment}
            onChange={this.dateChange} />
Copy the code
4. format
  • Type: string
  • Default: ‘YYYY-MM-DD’ (‘YYYY-MM-DD HH: MM :ss’ when showTime is true)
  • Description: Date string format
5. showTime
  • Types: bool
  • Default value: false
  • Description: Whether to display the time (hour minute second)
6. defaultTime
  • Type: string
  • Default value: none (If this parameter is not set, the current time is used by default)
  • Description: Default time (hour minute second), such as ’00:00:00′
7. minValue
  • Type: any of datepicker. VALUE_TYPE, independent of valueType
  • Default value: none
  • Description: Minimum value of an optional date
8. maxValue
  • Type: any of datepicker. VALUE_TYPE, independent of valueType
  • Default value: none
  • Description: Maximum number of available dates
9. placeholder
  • Type: string
  • Default: ‘Please select date’ (‘ Please select date and time ‘when showTime is true)
  • Note: Enter a prompt message
10. showClear
  • Types: bool
  • Default value: true
  • Note: Whether to display the empty button on the right side of the input box
11. disabled
  • Types: bool
  • Default value: false
  • Description: Whether the date picker is unavailable, true indicates that the date picker is unavailable
12. disabledDate
  • Type: func (required)
  • Default value: none
  • Note: Check whether the date is optional
    • The arguments:
      • {Moment} current Current date
    • Returns:
      • {Boolen} Whether this parameter is unavailable. True indicates that the current date is unavailable
13. disabledHours
  • Type: func (required)
  • Default value: none
  • Get an array of unavailable hours (valid if showTime is true)
    • The arguments:
      • {Moment} current Current date
    • Returns:
      • {Array} An unusable Array of hours
14. disabledMinutes
  • Type: func (required)
  • Default value: none
  • Get an array of unavailable minutes (valid if showTime is true)
    • The arguments:
      • {Number} selectedHour the currently selectedHour
      • {Moment} current Current date
    • Returns:
      • {Array} An unusable minute Array
15. disabledSeconds
  • Type: func (required)
  • Default value: none
  • Get array of unusable seconds (valid if showTime is true)
    • The arguments:
      • {Number} selectedHour the currently selectedHour
      • {Number} selectedMinute specifies the currently selectedMinute
      • {Moment} current Current date
    • Returns:
      • {Array} An unusable Array of seconds

Realize the DatePicker js

import React from 'react';
import PropTypes from 'prop-types';
import Calendar from 'rc-calendar';
import Picker from 'rc-calendar/lib/Picker';
import zhCN from 'rc-calendar/lib/locale/zh_CN';
import TimePickerPanel from 'rc-time-picker/lib/Panel';
import moment from 'moment';
import valueTypes from './utils/value-types';
import PickerPropTypes from './utils/picker-prop-types.js';
import valueConvertUtil from './utils/value-convert-util.js';
import 'moment/locale/zh-cn';
import './datePicker.scss';

/** * date picker */
export default class DatePicker extends React.Component {
    // Value type constants
    static VALUE_TYPE = valueTypes;

    // Check the input type
    static propTypes = {
        /** * select the callback function * after the date@param {Moment | Date | String | Number} Value Select the date value (corresponding to valueType) *@param {Moment} MomentValue Select the Moment value of the date */
        onChange: PropTypes.func.isRequired,
        // Date value type: datepicker. VALUE_TYPE
        valueType: PropTypes.oneOf(Object.keys(DatePicker.VALUE_TYPE).map( k= > DatePicker.VALUE_TYPE[k]) ),
        // Date value (must be a value of type specified by valueType)
        value: PickerPropTypes.dateValue,
        // Format of the date string
        format: PropTypes.string,
        // Whether to display the time (hour minute second)
        showTime: PropTypes.bool,
        // Default time. This parameter is valid when showTime is true, such as '00:00:00', or the current time is null
        defaultTime: PropTypes.string,
        // The minimum value of the available dates (any of datepicker.value_type, independent of valueType)
        minValue: PickerPropTypes.looseDateValue,
        // Maximum number of available dates (any of datepicker. VALUE_TYPE, independent of valueType)
        maxValue: PickerPropTypes.looseDateValue,
        // Enter a prompt
        placeholder: PropTypes.string,
        // Whether to display the empty button
        showClear:  PropTypes.bool,
        // Is not available
        disabled: PropTypes.bool,
        /** * Check whether the date is optional *@param {Moment} Current Current date *@return {Boolen} True indicates that the current date is not selectable. */
        disabledDate: PropTypes.func,
        /** * gets an array of unusable hours (valid if showTime is true) *@param {Moment} Current Current date *@return {Array<Number>} Unusable hour array */
        disabledHours: PropTypes.func,
        /** * Gets an array of unavailable minutes (valid if showTime is true) *@param {Number} SelectedHour the currently selectedHour *@param {Moment} Current Current date *@return {Array<Number>} An unusable minute array */
        disabledMinutes: PropTypes.func,
        /** * gets an array of unusable seconds (valid if showTime is true) *@param {Number} SelectedHour the currently selectedHour *@param {Number} SelectedMinute specifies the currently selectedMinute *@param {Moment} Current Current date *@return {Array<Number>} Unusable second array */
        disabledSeconds: PropTypes.func
    }

    // Enter the default value
    static defaultProps = {
        // Date value type, default string
        valueType: DatePicker.VALUE_TYPE.string,
        // Whether to display the time (hour, minute, second)
        showTime: false.// Whether to display the empty button
        showClear: true.// Whether it is unavailable. The default value is yes
        disabled: false
    }

    constructor(props) {
        super(props);

        const format = this.props.format || (this.props.showTime ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD');
        const momentValue = valueConvertUtil.convertToMoment(this.props.value, this.props.valueType, this.props.showTime, format);
        const minMomentValue = valueConvertUtil.convertToMoment(this.props.minValue, null.this.props.showTime, format);
        const maxMomentValue = valueConvertUtil.convertToMoment(this.props.maxValue, null.this.props.showTime, format);
        const defaultTimeValue = this.props.defaultTime ? moment(this.props.defaultTime, 'HH:mm:ss') : moment();
        const placeholder = this.props.placeholder ? this.props.placeholder : (this.props.showTime ? 'Please select date and time' : 'Please select a date');

        this.state = {
            // Moment value
            momentValue,
            // Time is a string of characters
            format,
            // Optional moment object with minimum time
            minMomentValue,
            // Optional moment object for the maximum time
            maxMomentValue,
            // The default time is minute and second
            defaultTimeValue,
            // Enter a prompt
            placeholder
        };
    }

    componentDidUpdate(prevProps, prevState) {
        this.receivePropsResetState(prevProps);
    }

    // Reset state based on the props changes
    receivePropsResetState (prevProps) {
        const format = this.props.format || (this.props.showTime ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD');
        if(prevProps.format ! = =this.props.format || prevProps.showTime ! = =this.props.showTime) {
            const momentValue = valueConvertUtil.convertToMoment(this.props.value, this.props.valueType, this.props.showTime, format);
            const minMomentValue = valueConvertUtil.convertToMoment(this.props.minValue, null.this.props.showTime, format);
            const maxMomentValue = valueConvertUtil.convertToMoment(this.props.maxValue, null.this.props.showTime, format);
            const placeholder = this.props.placeholder ? this.props.placeholder : (this.props.showTime ? 'Please select date and time' : 'Please select a date');

            this.setState({
                // Moment value
                momentValue,
                // Time is a string of characters
                format,
                // Optional moment object with minimum time
                minMomentValue,
                // Optional moment object for the maximum time
                maxMomentValue,
                // Enter a prompt
                placeholder
            });
        } else {
            if(prevProps.valueType ! = =this.props.valueType) {
                console.warn('The value of DatePicker component props. ValueType cannot be changed arbitrarily');
            }
            if(! valueConvertUtil.isSameValue(prevProps.value,this.props.value)) {
                const momentValue = valueConvertUtil.convertToMoment(this.props.value, this.props.valueType, this.props.showTime, format);
                this.setState({ momentValue });
            }
            if(prevProps.minValue ! = =this.props.minValue) {
                const minMomentValue = valueConvertUtil.convertToMoment(this.props.minValue, null.this.props.showTime, format);
                this.setState({ minMomentValue });
            }
            if(prevProps.maxValue ! = =this.props.maxValue) {
                const maxMomentValue = valueConvertUtil.convertToMoment(this.props.maxValue, null.this.props.showTime, format);
                this.setState({ maxMomentValue });
            }
            if(prevProps.defaultTime ! = =this.props.defaultTime) {
                const defaultTimeValue = this.props.defaultTime ? moment(this.props.defaultTime, 'HH:mm:ss') : moment();
                this.setState({ defaultTimeValue });
            }
            if(prevProps.placeholder ! = =this.props.placeholder) {
                const placeholder = this.props.placeholder ? this.props.placeholder : (this.props.showTime ? 'Please select date and time' : 'Please select a date');
                this.setState({ placeholder }); }}}/** * Convert other types to the moment object *@param Value Time value of other types */
    convertToMoment (value) {
        return valueConvertUtil.convertToMoment(value, this.props.valueType, this.props.showTime, this.state.format);
    }

    /** * Convert the moment object to another type *@param Obj moment object */
    convertFromMoment (obj) {
        return valueConvertUtil.convertFromMoment(obj, this.props.valueType, this.props.showTime, this.state.format);
    }

    // The event triggered after the date picker is selected
    onPickerChange = (value) = > {
        this.setState({ momentValue: value })

        if (!this.props.showTime || value === null) {
            this.props.onChange && this.props.onChange(this.convertFromMoment(value), value); }}// The event that is triggered when the date picker open state changes
    onOpenChange = (open) = > {
        if (this.props.showTime && ! open) {let value = this.state.momentValue;
            this.props.onChange && this.props.onChange(this.convertFromMoment(value), value); }}/ / to empty
    onClear = (event) = > {
        this.props.onChange && this.props.onChange(null.null);
        event.stopPropagation();
    };

    // Create time selector component (time minute second selector component)
    createTimePicker = (value) = > {
        if (this.props.showTime) {
            return <TimePickerPanel value={value} defaultValue={this.state.defaultTimeValue}/>;
        }
        return null;
    }

    /** * Check whether the date is optional *@param {Moment} Current moment object *@returns {boolean}* /
    disabledDate = (current) = > {
        if (!this.props.showTime) { // Do not display the time (minutes, seconds)
            let curValue = moment(current.format('YYYY-MM-DD'), 'YYYY-MM-DD');

            let { minMomentValue, maxMomentValue } = this.state;

            if (minMomentValue && curValue.isBefore(minMomentValue)) return true;
            if (maxMomentValue && curValue.isAfter(maxMomentValue)) return true;
        } else { // Display time (minutes, seconds)
            let curValue = this.state.momentValue;
            if ( curValue ) {
                curValue = moment(`${current.format('YYYY-MM-DD')} The ${this.convertToMoment(curValue).format('HH:mm:ss')}`.'YYYY-MM-DD HH:mm:ss');
            } else {
                curValue = moment(`${current.format('YYYY-MM-DD')} The ${this.state.defaultTimeValue.format('HH:mm:ss')}`.'YYYY-MM-DD HH:mm:ss');
            }

            let { minMomentValue, maxMomentValue } = this.state;
            let minVal, maxVal;
            if (minMomentValue) {
                minVal = moment(minMomentValue.format('YYYY-MM-DD'), 'YYYY-MM-DD')
                if (curValue.valueOf() < minVal.valueOf())  return true;
            }

            if (maxMomentValue) {
                if (maxMomentValue.format('HH:mm:ss') = = ='00:00:00') {
                    maxVal = maxMomentValue.clone();
                } else {
                    maxVal = moment(maxMomentValue.format('YYYY-MM-DD'), 'YYYY-MM-DD').add(moment.duration({'day' : 1}));
                }
                if (curValue.valueOf() >= maxVal.valueOf()) return true; }}if (this.props.disabledDate) {
            return this.props.disabledDate(current);
        }

        return false;
    }

    /** * Determine whether the time (hour, minute, second) is optional *@param {Moment} Current moment object *@returns {Object} Return the object */ that contains the disabledHours, disabledMinutes, and disabledSeconds functions
    disabledTime = (current) = > {
        // Create a continuous array of numbers based on the minimum and maximum values
        function createNumArray (minNum, maxNum) {
            let arr = [];
            for (let i = minNum; i <= maxNum; i++) {
                arr.push(i);
            }
            return arr;
        }

        // Maximum and minimum values for optional dates
        let { minMomentValue, maxMomentValue } = this.state;

        // If the date has been selected
        if (current) {
            // Get an array of unusable hours
            let disabledHours = () = > {
                let hours = [];
                if (minMomentValue && current.isSame(minMomentValue, 'day')) {
                    hours = createNumArray(0, minMomentValue.hour() - 1);
                }
                if (maxMomentValue && current.isSame(maxMomentValue, 'day')) {
                    hours = hours.concat(createNumArray(maxMomentValue.hour() + 1.23));
                }
                if (this.props.disabledHours) {
                    hours = hours.concat(this.props.disabledHours(current));
                }
                return hours;
            }

            // The method to get the unusable minute array
            let disabledMinutes = (selectedHour) = > {
                let minutes = [];
                if (minMomentValue && current.isSame(minMomentValue, 'day') && selectedHour === minMomentValue.hour()) {
                    minutes = createNumArray(0, minMomentValue.minute() - 1);
                }
                if (maxMomentValue && current.isSame(maxMomentValue, 'day') && selectedHour === maxMomentValue.hour()) {
                    minutes = minutes.concat(createNumArray(maxMomentValue.minute() + 1.59));
                }
                if (this.props.disabledMinutes) {
                    minutes = minutes.concat(this.props.disabledMinutes(selectedHour, current));
                }
                return minutes;
            }

            // Get the unusable second array method
            let disabledSeconds = (selectedHour, selectedMinute) = > {
                let seconds = [];
                if (minMomentValue && current.isSame(minMomentValue, 'day') && selectedHour === minMomentValue.hour() && selectedMinute === minMomentValue.minute()) {
                    seconds = createNumArray(0, minMomentValue.second() - 1);
                }
                if (maxMomentValue && current.isSame(maxMomentValue, 'day') && selectedHour === maxMomentValue.hour() && selectedMinute === maxMomentValue.minute()) {
                    seconds = seconds.concat(createNumArray(maxMomentValue.second() + 1.59));
                }
                if (this.props.disabledSeconds) {
                    seconds = seconds.concat(this.props.disabledSeconds(selectedHour, selectedMinute, current));
                }
                return seconds;
            }

            return {
                disabledHours,
                disabledMinutes,
                disabledSeconds
            }
        } else {
            // If no date is selected and the date range is limited, the time and second cannot be selected
            if (minMomentValue || maxMomentValue) {
                return {
                    disabledHours: () = > createNumArray(0.23),
                    disabledMinutes: () = > createNumArray(0.59),
                    disabledSeconds: () = > createNumArray(0.59)}; }else { // If no date is selected and the date range is not limited, use the disabledHours, disabledMinutes, and disabledSeconds of the input parameters to filter
                return {
                    disabledHours: () = > {
                        return this.props.disabledHours ? this.props.disabledHours(current) : [];
                    },
                    disabledMinutes: (selectedHour) = > {
                        return this.props.disabledMinutes ? this.props.disabledMinutes(selectedHour, current) : [];
                    },
                    disabledSeconds: (selectedHour, selectedMinute) = > {
                        return this.props.disabledSeconds ? this.props.disabledSeconds(selectedHour, selectedMinute, current) : []; }}; }}}render() {
        const dateValue = this.state.momentValue;
        const showClear = this.props.showClear && this.props.value;

        const calendar = (<Calendar locale={ zhCN }
                            dateInputPlaceholder={this.state.placeholder}
                            format={this.state.format}
                            timePicker={this.createTimePicker(dateValue)}
                            showDateInput={false}
                            disabledDate={this.disabledDate}
                            disabledTime={this.disabledTime} />);
        return (
            <Picker animation="slide-up"
                    calendar={calendar} 
                    value={dateValue}
                    onChange={this.onPickerChange}
                    onOpenChange={this.onOpenChange}
                    disabled={this.props.disabled}>
                {
                    ({ value }) => {
                        return (
                            <div className={'calendar-picker-box'+ (showClear ? ' calendar-picker-box-show-clear' :"')} >
                                <input placeholder={this.state.placeholder}
                                       disabled={this.props.disabled}
                                       className="date-picker-input"
                                       value={value && value.format && value.format(this.state.format) || ''}
                                       readOnly />
                                {showClear ?
                                    <span className="date-picker-clear" onClick={this.onClear} title="Empty">
                                        <i className="icon-guanbishibaimianxing clear-icon"></i>
                                    </span>
                                    : null}
                                <i className="icon icon-rili"></i>
                            </div>); }}</Picker>); }}Copy the code

I’m going to leave the styles out for now

“Feel free to discuss in the comments section.”

Hope to finish watching friends can give a thumbs-up, encourage once