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