自己实现antd 年选择器

自己实现antd年选择器

YearPicker.js

import React, { Component } from 'react';
import './yearpanel.less'
import YearPanel from 'rc-calendar/lib/year/YearPanel'
import gregorianCalendar from 'gregorian-calendar'
import ReactMixin from 'react-mixin';
import PickerMixin from 'antd/lib/date-picker/PickerMixin';
import locale from 'rc-calendar/lib/locale/zh_CN';
import placements from './placements'
import RcTrigger from 'rc-trigger';
import PropTypes from 'prop-types';

class YearPicker extends Component {
    constructor(props) {
        super(props);
        this.locale = this.getLocale();
        this.defaultCalendarValue = new gregorianCalendar(this.locale);
    }
    // 年选择器事件
    onYearPanelSelect = (current) => {
        this.props.onChange(current.getTime());
    }
    // 面板事件清除
    onPanelClear = () => {
        this.props.onPanelClear()
    }
    // esc隐藏
    onKeyDown = (e) => {
        if (e.keyCode === 40) {
            this.props.onEsc()
        }
    }
    render() {
        let { value, format } = this.props = this.props, prefixCls = "my-year-calendar ant-calendar";
        let text = value ? new Date(value).format(format) : '';
        // 年面板默认选中时间为当年
        this.defaultCalendarValue.setTime(value ? value : new Date().getTime());
        return (
            <div className={prefixCls}>
                <div className={prefixCls + "-input-wrap"}>
                    <div className={prefixCls + "-time-picker-wrap"}></div>
                    <div className={prefixCls + "-date-input-wrap"}>
                        <input className={prefixCls + "-input  "} value={text} placeholder="请选择年份" />
                    </div>
                    <a className={prefixCls + "-clear-btn"}
                        title="清除" onClick={this.onPanelClear}></a>
                </div>
                <YearPanel
                    locale={this.locale}
                    value={this.defaultCalendarValue}
                    rootPrefixCls={prefixCls}
                    onSelect={this.onYearPanelSelect}
                    style={{ position: 'static' }} />
            </div>
        )
    }
}
ReactMixin.onClass(YearPicker, PickerMixin);
// 默认的空事件
function noop() { }

export default class AntYearPicker extends Component {
    constructor(props) {
        super(props);
        this.state = {
            value: '',
            open: false
        }
    }
    // 设置值,并通知父组件值发生了变化
    onPanelChange = (e) => {
        const { onChange, format = 'yyyy' } = this.props, date = new Date(e);
        this.setValue(e);
        onChange({ value: date, formatValue: date.format(format) })
    }
    // 清除按钮 并通知父组件值发生了变化
    onPanelClear = () => {
        this.setValue(null)
        this.setOpen(false)
        onChange({ value: null, formatValue: '' })
    }
    // panelEsc事件
    onEsc = () => {
        this.setOpen(false);
        this.refs.picker.focus();
    }

    // esc隐藏
    onKeyDown = (e) => {
        if (e.keyCode === 40) {
            this.setOpen(true);
        }
    }
    // 设置open并分发open事件
    setOpen(open, callback) {
        let { onOpen, onClose } = this.props;
        if (this.state.open !== open) {
            this.setState({
                open
            }, callback)
            var _event = {
                open
            }
            if (open) {
                onOpen(_event)
            } else {
                onClose(_event)
            }
        }
    }
    // 设置value
    setValue = (value) => {
        if (!('value' in this.props)) {
            this.setState({
                value: value
            });
        }
    }
    // RcTrigger的隐藏和显示事件
    onVisibleChange = (open) => {
        this.setOpen(open)
    }
    // 获取value
    getValue = (e) => {
        // 这里需要判断value是
        // 字符串还是时间戳格式,还是日期格式
        if (typeof e === 'string') {
            e.length === 4 && (e = e + '/01/01');
            return e ? new Date(e).getTime() : null;
        } else if (typeof e === 'number') {
            return e
        } else if (e instanceof Date) {
            return e;
        } else {
            return null;
        }
    }

    componentWillReceiveProps(nextProps) {
        if ('value' in nextProps) {
            let time = this.getValue(nextProps.value);
            this.setState({
                value: time
            });
        }
        if ('open' in nextProps) {
            this.setState({ open: nextProps.open })
        }
    }
    componentWillMount() {
        let { value,open } = this.props;
        let time = this.getValue(value);
        this.setState({
            value: time,
            open
        });
    }
    render() {
        const {
            placeholder,
            format,
            className,
            style,
            align,
            placement,
            disabled,
            transitionName,
            prefixCls
        } = this.props,
            { value, open } = this.state;
        let text = value ? new Date(value).format(format) : '';
        return <RcTrigger
            prefixCls={prefixCls + '-container'}
            popupClassName={prefixCls + '-panel-narrow'}
            popup={<YearPicker
                locale={locale}
                onChange={this.onPanelChange}
                onPanelClear={this.onPanelClear}
                onEsc={this.onEsc}
                format={format}
                value={value}
            />}
            popupAlign={align}
            builtinPlacements={placements}
            popupPlacement={placement}
            action={disabled ? [] : ['click']}
            destroyPopupOnHide={true}
            // getPopupContainer={getPopupContainer}
            popupTransitionName={transitionName}
            popupVisible={open}
            onPopupVisibleChange={this.onVisibleChange}
        >
            <span className={prefixCls + className} style={style}>
                <input className={prefixCls + '-input ant-input'}
                    ref="picker"
                    type="text"
                    placeholder={placeholder}
                    readOnly={true}
                    onKeyDown={this.onKeyDown}
                    value={text}
                    disabled={disabled}
                    style={{ height: '100%' }}
                ></input>
                <span className={prefixCls + '-icon'}></span>
            </span>
        </RcTrigger>
    }
}
AntYearPicker.propTypes = {
    prefixCls: PropTypes.string,// 组件前置class名
    locale: PropTypes.object,// 时间本地化设置参数
    value: PropTypes.any,// value值
    disabled: PropTypes.bool,// 是否禁用
    // allowEmpty: PropTypes.bool,// 是否允许为空
    // defaultValue: PropTypes.object,
    open: PropTypes.bool,// 面板打开状态
    // defaultOpen: PropTypes.bool,
    align: PropTypes.object,
    placement: PropTypes.any,// 弹出面板的位置
    transitionName: PropTypes.string,// 动画
    // getPopupContainer: PropTypes.func,
    placeholder: PropTypes.string,
    format: PropTypes.string,// 日期格式
    style: PropTypes.object,// 样式
    className: PropTypes.string,// class名
    onChange: PropTypes.func,// value变化事件
    onOpen: PropTypes.func,// open为true时的事件
    onClose: PropTypes.func// open为false时的事件
}
AntYearPicker.defaultProps = {
    prefixCls: 'ant-calendar-picker',
    locale: locale,
    defaultOpen: false,
    disabled: false,
    style: {},
    className: '',
    align: {},
    // allowEmpty: true,
    placement: 'bottomLeft',
    onChange: noop,
    onOpen: noop,
    onClose: noop,
    placeholder: '',
    transitionName: '',
    format: 'yyyy年',

}

placement.js

'use strict';

Object.defineProperty(exports, '__esModule', {
  value: true
});
var autoAdjustOverflow = {
  adjustX: 1,
  adjustY: 1
};

var targetOffset = [0, 0];

var placements = {
  bottomLeft: {
    points: ['tl', 'tl'],
    overflow: autoAdjustOverflow,
    offset: [0, -3],
    targetOffset: targetOffset
  },
  bottomRight: {
    points: ['tr', 'tr'],
    overflow: autoAdjustOverflow,
    offset: [0, -3],
    targetOffset: targetOffset
  },
  topRight: {
    points: ['br', 'br'],
    overflow: autoAdjustOverflow,
    offset: [0, 3],
    targetOffset: targetOffset
  },
  topLeft: {
    points: ['bl', 'bl'],
    overflow: autoAdjustOverflow,
    offset: [0, 3],
    targetOffset: targetOffset
  }
};

exports['default'] = placements;
module.exports = exports['default'];

样式文件yearpanel.less

.my-year-calendar .ant-calendar-year-panel{
    position: relative;
    top: 0;
}

使用

import './index.less'
import React from 'react';
import YearPicker from './YearPicker/index'
class Test extends React.Component {
   constructor(props) {
      super(props)
      this.state = {
         value: null,
         formatValue:''
      }
   }
   onChange = (value) => {
      this.setState({ ...value })
   }
   onOpen = () => {
      console.log('open')
   }
   onClose = () => {
      console.log('close')
   }
   render() {
      const { value,formatValue } = this.state
      return (
         <div style={{ width: '400px', padding: '20px 50px' }}>
            <p>您选中的年份为{formatValue}</p>
            <span><span>年选择器</span>
               <YearPicker
                  value={value}
                  style={{ height: '34px' }}
                  onChange={this.onChange}
                  onOpen={this.onOpen}
                  onClose={this.onClose}/></span>
         </div>
      )
   }

}
export default Test

项目文件目录
自己实现antd 年选择器_第1张图片
图标没出来是因为我没有引用字体库,但是不影响使用
自己实现antd 年选择器_第2张图片

自己实现antd 年选择器_第3张图片

你可能感兴趣的:(react,reactjs)