不知道为什么蚂蚁金服团队没有在ant design的DatePicker中单独给出选择年份的组件,这给我们这种懒人造成了很大的痛苦,自己手造轮子是很麻烦的。毕竟只是一个伸手党,emmmmm.....

然后就打算自己手撸了,首先去偷看了蚂蚁自己组件的样式,打算照着搬下来。后来发现下面的item是用的table布局,这种布局是我最厌恶的,还是换种方式吧,ul>li,嗯,我最喜欢的

然后开始。

代码如下:

/**
* 使用方法
* 引入:
* import YearPicker from "@/common/widget/YearPicker";//路径按照自己的来
* // 获取年份值
filterByYear = value => {
console.log(value);
};
* <YearPicker
operand={12}//点击左箭头或右箭头一次递增的数值,可以不写,默认为0
callback={this.filterByYear}//用于获取最后选择到的值
/>
*/
import React, { Component } from "react";
import { Icon } from "antd";
import "../css/calendar.less";//这个文件自己选择一个温暖的地方放 class YearPicker extends Component {
constructor(props) {
super(props);
this.state = {
isShow: false,
selectedyear: "",
years: []
};
} componentWillMount() {
let { defaultValue } = this.props;
this.setState({ selectedyear: defaultValue });
}
componentDidMount() {
let _this = this;
document.addEventListener(
"click",
function(e) {
const { isShow } = _this.state;
let clsName = e.target.className;
if (
clsName.indexOf("calendar") === -1 &&
e.target.tagName !== "BUTTON" &&
isShow
) {
_this.hide();
}
},
false
);
}
//初始化数据处理
initData = (operand, defaultValue) => {
operand = operand ? operand : 12;
let year = defaultValue - 1970;
let curr = year % operand;
let start = defaultValue - curr;
let end = defaultValue + operand - 1 - curr;
this.getYearsArr(start, end);
};
// 获取年份范围数组
getYearsArr = (start, end) => {
let arr = [];
for (let i = start; i <= end; i++) {
arr.push(Number(i));
}
this.setState({
years: arr
});
};
// 显示日历年组件
show = () => {
const { selectedyear } = this.state;
let { operand } = this.props;
operand = operand ? operand : 12;
this.initData(operand, selectedyear);
this.setState({ isShow: true });
};
// 隐藏日期年组件
hide = () => {
this.setState({ isShow: false });
};
// 向前的年份
prev = () => {
const { years } = this.state;
if (years[0] <= 1970) {
return;
}
this.getNewYearRangestartAndEnd("prev");
};
// 向后的年份
next = () => {
this.getNewYearRangestartAndEnd("next");
}; // 获取新的年份
getNewYearRangestartAndEnd = type => {
const { selectedyear, years } = this.state;
let operand = Number(this.props.operand);
operand = operand ? operand : 12;
let start = Number(years[0]);
let end = Number(years[years.length - 1]);
let newstart;
let newend;
if (type == "prev") {
newstart = parseInt(start - operand);
newend = parseInt(end - operand);
}
if (type == "next") {
newstart = parseInt(start + operand);
newend = parseInt(end + operand);
}
this.getYearsArr(newstart, newend);
}; // 选中某一年
selects = e => {
let val = Number(e.target.value);
this.hide();
this.setState({ selectedyear: val });
if (this.props.callback) {
this.props.callback(val);
}
}; render() {
const { isShow, years, selectedyear } = this.state; return (
<div className="calendar-wrap">
<div className="calendar-input">
<input
className="calendar-value"
placeholder="请选择年份"
onFocus={this.show}
value={selectedyear}
readOnly
/>
<Icon type="calendar" className="calendar-icon" />
</div>
{isShow ? (
<List
data={years}
value={selectedyear}
prev={this.prev}
next={this.next}
cback={this.selects}
/>
) : (
""
)}
</div>
);
}
}
const List = props => {
const { data, value, prev, next, cback } = props;
return (
<div className="calendar-container">
<div className="calendar-head-year">
<Icon
type="double-left"
className="calendar-btn prev-btn"
title=""
onClick={prev}
/>
<span className="calendar-year-range">{value}</span>
<Icon
type="double-right"
className="calendar-btn next-btn"
title=""
onClick={next}
/>
</div>
<div className="calendar-body-year">
<ul className="calendar-year-ul">
{data.map((item, index) => (
<li
key={index}
title={item}
className={
item == value
? "calendar-year-li calendar-year-selected"
: "calendar-year-li"
}
>
<button onClick={cback} value={item}>
{item}
</button>
</li>
))}
</ul>
</div>
</div>
);
}; export default YearPicker;

less代码:

@focuscolor: #108ee9;
@bordercolor: #d9d9d9;
/*这部分根据你自己的容器样式,我这个地方是因为公用组件的原因需要设置*/
#wrapper .toolbar {
overflow: inherit !important;
}
#wrapper .toolbar > div:after {
content: "";
display: block;
visibility: hidden;
width:;
clear: both;
}
/*---以下为必备样式----*/
.calendar-wrap {
position: relative;
.calendar-input {
width: 151px;
position: relative;
cursor: pointer;
.calendar-icon {
position: absolute;
right: 10px;
top: 10px;
color: #919191;
}
input {
width: 151px;
height: 31px;
border: 1px solid @bordercolor;
border-radius: 4px;
font-size: 12px;
outline: none;
display: block;
padding: 6px 7px;
transition: all 0.3s;
&:hover,
&:active {
border-color: @focuscolor;
}
}
} .calendar-container {
width: 232px;
outline: none;
border-radius: 4px;
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.2);
border: 1px solid @bordercolor;
position: absolute;
top:;
left:;
z-index:;
background-color: #fff;
line-height: 1.5;
}
.calendar-head-year {
height: 34px;
line-height: 34px;
text-align: center;
width: 100%;
position: relative;
border-bottom: 1px solid #e9e9e9;
.calendar-year-range {
padding: 0 2px;
font-weight: bold;
display: inline-block;
color: rgba(0, 0, 0, 0.65);
line-height: 34px;
}
.calendar-btn {
position: absolute;
top:;
color: rgba(0, 0, 0, 0.43);
padding: 0 5px;
font-size: 12px;
display: inline-block;
line-height: 34px;
cursor: pointer;
&:hover {
color: @focuscolor;
}
}
.prev-btn {
left: 7px;
}
.next-btn {
right: 7px;
}
}
.calendar-body-year {
width: 100%;
height: 218px;
.calendar-year-ul {
list-style: none;
.calendar-year-li {
float: left;
text-align: center;
width: 76px;
cursor: pointer;
> button {
cursor: pointer;
outline: none;
border:;
display: inline-block;
margin: 0 auto;
color: rgba(0, 0, 0, 0.65);
background: transparent;
text-align: center;
height: 24px;
line-height: 24px;
padding: 0 6px;
border-radius: 4px;
transition: background 0.3s ease;
margin: 14px 0;
&:hover {
color: @focuscolor;
}
}
}
.calendar-year-selected {
> button {
background: #108ee9;
color: #fff;
&:hover {
color: #fff;
}
}
}
}
}
}

以上代码在IE10,11、FireFox, Chrome, Safari下亲测兼容良好

接下来说说,这个过程中遇到的问题:

1、点击组件外部任意地方需要关闭控件

以为显示的属性设置在组件内部的state中,因此当时有点懵逼,一开始想用redux store来控制,然后觉得这个强行依赖太恶心了,放弃

然后,想到在document上绑定click事件,虽然有点违背react不直接操作dom的原则。但是这是我这种智商能想到的比较好的方式了

(偷偷看了蚂蚁的方式,将整个选择的组件与input框隔离成独立的部分,采用 类似全屏遮罩层的方式,检测input在窗口中的位置来设置展示组件的位置,这样确实对于控制点击外部任意处关闭控件。但是这样属于一个控件的东西被拆分不是我这种一根筋的人能接受的)

so, 我还是倔强的使用了自己的方式

componentDidMount() {
let _this = this;
document.addEventListener(
"click",
function(e) {
const { isShow } = _this.state;
let clsName = e.target.className;
if (
clsName.indexOf("calendar") === -1 &&
e.target.tagName !== "BUTTON" &&
isShow
) {
_this.hide();
}
},
false
);
}

2. 当外部容器设置了overflow:hidden 的情况时,控件会被遮挡

这个问题的话,额, 我就是去掉overflow:hidden, 然后给容器清除浮动或者设置固定高度

(一般需要设置overflow:hidden也是因为使用了浮动)

好了,我废话就这么多了,哈哈哈

时间选择控件YearPicker(基于React,antd)的更多相关文章

  1. 基于zepto的移动端日期和时间选择控件

    前段时间给大家分享过一个基于jQuery Mobile的移动端日期时间拾取器,大家反应其由于加载过大的插件导致影响调用速度.那么今天我把从网络上搜集到的两个适合移动端应用的日期和时间选择插件分享给大家 ...

  2. bootstrap-datetimepicker:基于twitter bootstrap的日期/时间选择控件

    bootstrap-datetimepicker是一个基于twitter bootstrap的简单日期/时间选择控件. <!DOCTYPE HTML> <html> <h ...

  3. Extjs DateTime 日期时间选择控件 (非点击日期强制选择) 支持4.0以上

    Extjs的日期控件,仅仅能支持到日期选择,对时间的选择并不完好.而网上下载的控件,都是基于Ext.form.dateField 开发.在选中日期后自己主动选择,并隐藏此选择窗体. 在经过一番改造后, ...

  4. 关于使用jqmobi前端框架在phonegap平台上开发时的日期时间选择控件

    jqmobi(appframework)作为Intel的一款html5移动前端框架,以其自身轻量级和容易上手获得了很多移动HTML5开发者的喜爱,相对于jquerymobile,它可以说将jQuery ...

  5. win10 uwp 好看的时间选择控件

    本文告诉大家我找到的好看的时间选择控件 先给大家看一下图,然后就知道我说的是什么 首先需要安装 Nuget ,搜索 DeanChalk.UWP.TimePicker 或输入Install-Packag ...

  6. WebDriver测试EXT控件(基于C#)

    WebDriver测试EXT控件(基于C#)http://www.docin.com/p-748096409.html

  7. wpf timePicker 时间选择控件

    wpf里有日期选择控件,但没有时间选择控件.其他地方也有类似的,但效果并不太好,而且复杂.所以就自己写了个.参考codeproject上的. 分两部分. 第一部分是.cs文件.也就是control控件 ...

  8. 共享MFC每周时间选择控件代码

    自己写的周时间选择控件,原理就是在Static上用GDI画图. 支持选择每周内每一天内的任意时间段,可以任意拖动修改时间段,任意合并时间段 效果如下图: VS2012代码下载:https://gith ...

  9. WinForm时间选择控件(DateTimePicker)如何选择(显示)时分秒

    C# Windows窗体应用中,用到时间选择控件DateTimePicker,发现不能选择时分秒,难道要自己写一个控件?! 答案是否定的,通过属性修改是可以选择时间的,DateTimePicker完全 ...

随机推荐

  1. Docker2之Service

    Make sure you have published the friendlyhello image you created by pushing it to a registry. We’ll ...

  2. System.ServiceProcess与System.Configuration.Install命名空间的介绍

    System.ServiceProcess 命名空间提供用于实现.安装和控制 Windows 服务应用程序的类.服务是长期运行的可执行文件,其运行没有用户界面 System.ServiceProces ...

  3. ARM伪指令

    1.伪指令是什么 ARM伪指令不是ARM指令集中的指令,只是为了编程方便人们定义了伪指令. 在汇编时这些指令将会被等效的ARM指令或arm指令的组合代替. 编程时可以像其他ARM指令一样使用伪指令,区 ...

  4. 折腾了好久的地图缩放 ngui 各种偷懒实现

    当时找到一篇cocos2dx 地图缩放的  很遗憾我用不了  也要记录一下 免得以后用ugui可以用 转 http://blog.csdn.net/cocosnode/article/details/ ...

  5. 【BZOJ】3295: [Cqoi2011]动态逆序对

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3295 mamaya,弱鸡xrdog终于会写树套树啦.... 将树状数组中每一个节点看成一棵 ...

  6. CentOS6.X、7.X下Jenkins的安装及使用

    一.相关概念 1.1 Jenkins概念: Jenkins是一个功能强大的应用程序,允许持续集成和持续交付项目,无论用的是什么平台.这是一个免费的源代码,可以处理任何类型的构建或持续集成.集成Jenk ...

  7. ext4.2常用的几种弹框

    以下记录了自己在做项目时,经常用到的几种ext弹框.项目中使用的ext是4.2版本的. 1. Ext.Msg.alert() 使用此种方式时,如果提示信息过长则提示信息会被覆盖掉一部分. Ext.Ms ...

  8. Eclipse调试DEBUG时快速查看某个变量的值的快捷键、快速跳转到某行的快捷键

    Eclipse调试DEBUG时快速查看某个变量的值的快捷键 Ctrl + Shift + i

  9. 力扣(LeetCode)292. Nim游戏 巴什博奕

    你和你的朋友,两个人一起玩 Nim游戏:桌子上有一堆石头,每次你们轮流拿掉 1 - 3 块石头. 拿掉最后一块石头的人就是获胜者.你作为先手. 你们是聪明人,每一步都是最优解. 编写一个函数,来判断你 ...

  10. 认识flask框架-2

    1.json:基于键值对的字符串,轻量级的数据交互格式,用来传输数据 2.json模块 dumps:把字典转化成json字符串. loads:把json字符串转成字典. dump.load操作的是文件 ...