时间选择控件YearPicker(基于React,antd)
不知道为什么蚂蚁金服团队没有在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)的更多相关文章
- 基于zepto的移动端日期和时间选择控件
前段时间给大家分享过一个基于jQuery Mobile的移动端日期时间拾取器,大家反应其由于加载过大的插件导致影响调用速度.那么今天我把从网络上搜集到的两个适合移动端应用的日期和时间选择插件分享给大家 ...
- bootstrap-datetimepicker:基于twitter bootstrap的日期/时间选择控件
bootstrap-datetimepicker是一个基于twitter bootstrap的简单日期/时间选择控件. <!DOCTYPE HTML> <html> <h ...
- Extjs DateTime 日期时间选择控件 (非点击日期强制选择) 支持4.0以上
Extjs的日期控件,仅仅能支持到日期选择,对时间的选择并不完好.而网上下载的控件,都是基于Ext.form.dateField 开发.在选中日期后自己主动选择,并隐藏此选择窗体. 在经过一番改造后, ...
- 关于使用jqmobi前端框架在phonegap平台上开发时的日期时间选择控件
jqmobi(appframework)作为Intel的一款html5移动前端框架,以其自身轻量级和容易上手获得了很多移动HTML5开发者的喜爱,相对于jquerymobile,它可以说将jQuery ...
- win10 uwp 好看的时间选择控件
本文告诉大家我找到的好看的时间选择控件 先给大家看一下图,然后就知道我说的是什么 首先需要安装 Nuget ,搜索 DeanChalk.UWP.TimePicker 或输入Install-Packag ...
- WebDriver测试EXT控件(基于C#)
WebDriver测试EXT控件(基于C#)http://www.docin.com/p-748096409.html
- wpf timePicker 时间选择控件
wpf里有日期选择控件,但没有时间选择控件.其他地方也有类似的,但效果并不太好,而且复杂.所以就自己写了个.参考codeproject上的. 分两部分. 第一部分是.cs文件.也就是control控件 ...
- 共享MFC每周时间选择控件代码
自己写的周时间选择控件,原理就是在Static上用GDI画图. 支持选择每周内每一天内的任意时间段,可以任意拖动修改时间段,任意合并时间段 效果如下图: VS2012代码下载:https://gith ...
- WinForm时间选择控件(DateTimePicker)如何选择(显示)时分秒
C# Windows窗体应用中,用到时间选择控件DateTimePicker,发现不能选择时分秒,难道要自己写一个控件?! 答案是否定的,通过属性修改是可以选择时间的,DateTimePicker完全 ...
随机推荐
- 到底什么是 ROI Pooling Layer ???
到底什么是 ROI Pooling Layer ??? 只知道 faster rcnn 中有 ROI pooling, 而且其他很多算法也都有用这个layer 来做一些事情,如:SINT,检测的文章等 ...
- [ajaxupload] - 上传文件同时附件参数值
$.ajax({ url: '/excel/importExcel?instance='+"品种1", type: 'POST', data: formData, 上面前端通过?拼 ...
- 常用的 Linux 命令
列出文件列表:ls [参数 -a -l]创建目录和移除目录:mkdir rmdir用于显示文件后几行内容:tail打包:tar -xvf打包并压缩:tar -zcvf查找字符串:grep显示当前所在目 ...
- WijmoJS 全面支持 Angular 7
概述 首先恭喜Angular团队发布Angular 7.0.0版本! 对于大多数开发人员,只需要执行一个命令就可以更新到Angular 7: ng update \@angular/cli \@ang ...
- PTA 堆栈操作合法性(20 分)
7-1 堆栈操作合法性(20 分) 假设以S和X分别表示入栈和出栈操作.如果根据一个仅由S和X构成的序列,对一个空堆栈进行操作,相应操作均可行(如没有出现删除时栈空)且最后状态也是栈空,则称该序列是合 ...
- 将一个符合URL格式的字符串变成链接
function replaceURLWithHTMLLinks(text) { /* Example: >>> GateOne.Utils.replaceURLWithHTMLLi ...
- 每天一个小程序—第0001题(uuid模块)
第 0001 题: 做为 Apple Store App 独立开发者,你要搞限时促销,为你的应用生成激活码(或者优惠券),使用 Python 如何生成 200 个激活码(或者优惠券)? 一开始以为是 ...
- Python 网页解析器
Python 有几种网页解析器? 1. 正则表达式 2.html.parser (Python自动) 3.BeautifulSoup(第三方)(功能比较强大) 是一个HTML/XML的解析器 4.lx ...
- File操作-将数据库里的数据写入到指定路径的txt文件里
package com.Cristin.File;//将数据库里的数据写入到指定路径的txt文件里 import java.io.File;import java.io.FileOutputStrea ...
- UnicodeEncodeError: 'gbk' codec can't encode character '\u25aa' in position 15: illegal multibyte sequence
UnicodeEncodeError: 'gbk' codec can't encode character '\u25aa' in position 15: illegal multibyte se ...