不知道为什么蚂蚁金服团队没有在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. 题解——洛谷P3275 [SCOI2011]糖果

    一道条件非常多的差分约束 把\( a < b \)转化为\( a-b \le -1\)就可做了 \( a>b \)的情况同理 若有负环则无解输出-1 注意本题中要求每个人都有糖果 所以假设 ...

  2. HDU 4918 Query on the subtree(动态点分治+树状数组)

    题意 给定一棵 \(n\) 个节点的树,每个节点有点权.完成 \(q\) 个操作--操作分两种:修改点 \(x\) 的点权.查询与 \(x\) 距离小于等于 \(d\) 的权值总和. \(1 \leq ...

  3. jquery选择器扩展之样式选择器

    https://github.com/wendux/style-selector-jQuery-plugin http://blog.csdn.net/duwen90/article/details/ ...

  4. -第3章 jQuery方法实现下拉菜单显示和隐藏

    知识点 jquery 的引入方式 本地下载引入 在线引入 children 只获取子元素,不获取孙元素 show() 显示. hide() 隐藏. 完整代码 <!-- Author: XiaoW ...

  5. 关于jQ的Ajax操作

    jQ的Ajax操作 什么是AJAX AJAX = 异步的javascript和XML(Asynchronous Javascript and XML) 它不是一门编程语言,而是利用JavaScript ...

  6. HDU 3526 Computer Assembling(最小割)

    http://acm.hdu.edu.cn/showproblem.php?pid=3526 题意:有个屌丝要配置电脑,现在有n个配件需要购买,有两家公司出售这n个配件,还有m个条件是如果配件x和配件 ...

  7. JS代码排版工具

    有时候从网页上下载的js文件删除了空格,看起来就是一整段,还是蛮影响开发效率的,在CSDN上找到一个排版工具,用掉了我最后一个积分,所以在这儿分享一下: 百度云:链接:http://pan.baidu ...

  8. 设计模式(五)Builder Pattern建造者模式

    在我们日常生活中,如构建一个飞船,一个手机,一栋建筑,都会有非常复杂的组装,这时候应该用到建造者模式 以建造一个飞船为例 案例:造小页飞船 1.飞船各部分元件 package com.littlepa ...

  9. Python day1_Base1笔记

    1.helloworld print('helloword') 2.输入输出 a=input('Please input a value') print(a) 3.标识符 1.由字母数字下划线构成 2 ...

  10. SQL关于WHERE 的计算次序

    WHERE可包含任意数目的AND和OR操作符.允许两者结合以进行复杂 和高级的过滤. 但是OR和AND操作符是有先后次序的. 比如,原意是想找出 3班和5班年龄为21岁的同学,使用 :SELECT * ...