时间选择控件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完全 ...
随机推荐
- tomcat使用spring-loaded实现应用热部署
springloaded官方说明: Spring Loaded is a JVM agent for reloading class file changes whilst a JVM is runn ...
- P2517 [HAOI2010]订货
思路 费用流水题 对每月拆点,入点向出点连cap=ui的边,s向入点连cost=di的边,i的入点向i+1的入点连cap=S的边即可 代码 #include <cstdio> #inclu ...
- P4313 文理分科
思路 遇到这种利益冲突的最终利益最大化问题 考虑转化为最小割,使得损失的价值最小 相当于文科是S,理科是T,选出最小割就是确定损失代价最小的方案 然后就把S向每个点连一条cap=art[i][j]的边 ...
- 论文笔记之:Deep Attributes Driven Multi-Camera Person Re-identification
Deep Attributes Driven Multi-Camera Person Re-identification 2017-06-28 21:38:55 [Motivation] 本文 ...
- 使用Numpy实现卷积神经网络(CNN)
import numpy as np import sys def conv_(img, conv_filter): filter_size = conv_filter.shape[1] result ...
- 【转载】SeleniumIDE入门
http://www.open-open.com/lib/view/open1452488109558.html
- 【NOIP 2018】Day2 T3 保卫王国
Problem Description Z 国有\(n\)座城市,\(n - 1\)条双向道路,每条双向道路连接两座城市,且任意两座城市 都能通过若干条道路相互到达. Z 国的国防部长小 Z 要在城市 ...
- 八皇后问题 递归实现 C语言 超详细 思路 基础
八皇后问题 :假设 將八个皇后放到国际象棋盘上,使其两两之间无法相互攻击.共有几种摆法? 基础知识: 国际象棋里,棋盘为8X8格. 皇后每步可以沿直线.斜线 走任意格. 思路: 1.想把8个皇后放进去 ...
- hdu 6053 TrickGCD 筛法
TrickGCD Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others) Probl ...
- CentOS7 下curl使用
curl工具工具的主页:https://curl.haxx.se/NAMEcurl - transfer a URL SYNOPSIScurl [options] [URL...] DESCRIPTI ...