最近花了差很少快两周的空闲时间打造了一个日期选择组件,先看看效果html
能够说是一个常常要用到,不多人会主动去实现的一个组件,毕竟实现起来仍是要必定的时间的,因此平时工做之余就能够试着打造一些基础组件库,既能够锻炼本身的基本功,又能够为公司为社区作贡献~git
先看一下用法吧,推荐查看文档,能够实时交互github
一般有如下几种安装方式npm
npm i xy-ui
<script type="module" src="https://unpkg.com/xy-ui/components/xy-pagination.js"></script> <!--或者--> <script type="module"> import 'https://unpkg.com/xy-ui/components/xy-pagination.js' </script>
直接从github拷贝源码。api
使用数组
<xy-date-picker></xy-date-picker>
一个标签的事,开箱即用,多是使用起来最方便的日期选择器了。ui
这里简单介绍一下日期的生成原理this
要实现一个月的展现,通常分为三个部分,分别为前一个月,当前月,下一个月spa
为此,咱们须要知道设计
1.前一个月的最后一天
2.当前月的天数及当前月第一天是周几(便于摆放位置)
假如前一个月最后一天是31号,而且当月的第一天是周二及总天数30,那么这个月的排列就肯定了
日 | 一 | 二 | 三 | 四 | 五 | 六 |
---|---|---|---|---|---|---|
30 | 31 | 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 1 | 2 | 3 |
首先是获取一个月的最后一天,一般每月的天数是固定的,只有二月不固定,有一种作法是把二月单独列出来,经过计算闰年的方式来判断是29仍是28。
其实还有一种方式可能方便,咱们能够直接利用日期的容错机制,好比
new Date(2019,2,1) //2019年3月1日 new Date(2019,2,0) //2019年3月1日的前一天,也就是2019年2月的最后一天
而后获取当天的日期,也就是当月天数
new Date(2019,2,0).getDate() //28
而后是获取一个月的第一天是星期几,这个比较容易
new Date(2019,2,1).getDay() //5,周五
而后咱们能够经过这些信息组合出一个月份信息
function getDays(year,month){ const lastdays = new Date(year,month-1,0).getDate(); const days = new Date(year,month,0).getDate(); const week = new Date(year,month-1,1).getDay(); const prev = Array.from({length:week},(el,i)=>(month==0?year-1:year)+'-'+(month==0?12:month-1)+'-'+(lastdays+i-week+1)); const current = Array.from({length:days},(el,i)=>year+'-'+month+'-'+(i+1)); const next = Array.from({length:42 - days - week},(el,i)=>(month==12?year+1:year)+'-'+(month==12?1:month+1)+'-'+(i+1)); return [...prev,...current,...next]; }
这里简单作了一个在控制台输出日历
源码以下,小伙伴能够试试
function renderCalendar(d){ const date = new Date(d||new Date); const year = date.getFullYear(); const month = date.getMonth(); const day = date.getDate(); const lastdays = new Date(year,month,0).getDate(); const days = new Date(year,month+1,0).getDate(); const week = new Date(year,month,1).getDay(); const prev = Array.from({length:week},(el,i)=>([month==0?year-1:year,month==0?12:month,lastdays+i-week+1])); const current = Array.from({length:days},(el,i)=>[year,month+1,i+1]); const next = Array.from({length:42 - days - week},(el,i)=>([month==11?year+1:year,month==11?1:month+2,i+1])); const final = [...prev,...current,...next]; const now = Array.from({length:6},(el,i)=>final.slice(i * 7, i * 7 + 7)); const s = `———————————————————————————————————— ${year+' - '+(month+1+'').padStart(2,0)} %c———————————————————————————————————— | Su | Mo | Tu | We | Th | Fr | Sa | ———————————————————————————————————— %c${now.map(el=>el.map(m=>(m[2]==1?'%c':'')+'| '+((m[2]+'').padStart(2,' ')+' ')).join('')+'|\n————————————————————————————————————\n').join('')} ` console.clear(); console.log(s,"font-weight:bold;color:blue","color:#999","color:#000","color:#999") }
以上就是日期生成原理了,进一步能够实现日期切换,单选,范围选择等功能。
xy-date-picker
定义如下几种属性,结合使用适用性更广。
defaultvalue
能够给日期选择器指定一个初始日期defaultvalue
,取值为合法的时间戳字符串DataString
,默认为当前日期。
支持形如如下的字符串,可参考Date.parse()
"2019-2-28" "2019-02-28" "2019/2/28" "2019,2,28" "2019 2 28" "Feb 28 2019" //...其余日期格式 //以上均表示2019年2月28日。
<xy-date-picker defaultvalue="2019-2-28"></xy-date-picker>
type
支持设置日期选择类型,可选择date
(默认)、month
、year
,分别实现日期选择器、月选择器、年选择器。
<xy-date-picker></xy-date-picker> <xy-date-picker type="month"></xy-date-picker> <xy-date-picker type="year"></xy-date-picker>
value
、日期date
设置或返回日期选择器的value
属性值。值为当前类型下的日期,格式形如2019-10-10
。
返回日期的标准格式date
,能够将值转换成任意格式的日期。
//value "2019-08-31" //date "Sat Aug 31 2019 14:54:05 GMT+0800 (中国标准时间)"
能够经过JavaScript
设置或获取。
date.value; //获取 date.date; //获取 date.value = '2019-10-10'; //原生属性操做 date.getAttribute('value'); date.getAttribute('date'); date.setAttribute('value','2019-10-10');
min
、最大值max
设置日期选择范围,超出范围以外的不可选中,格式同defaultvalue
。
<xy-date-picker min="2019-8-20" max="2019-12-21"></xy-date-picker> <xy-date-picker type="month" min="2019-5" max="2019-12"></xy-date-picker> <xy-date-picker type="year" min="2018" max="2050"></xy-date-picker>
disabled
经过disabled
能够禁用,禁用后没法打开日期选择器。
<xy-date-picker disabled></xy-date-picker>
经过dir
能够设置日期选择器方向,默认为bottomleft
,能够取值top
、right
、bottom
、left
、topleft
、topright
、righttop
、rightbottom
、bottomleft
、bottomright
、lefttop
、leftbottom
。当你的日期选择器位于屏幕边缘时能够调整该属性。
<xy-date-picker dir="righttop"></xy-date-picker>
range
添加range
属性能够实现日期范围选择。
<xy-date-picker range></xy-date-picker>
能够指定一个默认范围defaultvalue
,格式形如2019-10-10~2019-12-31
,用~
连接。默认为当前日期。
<xy-date-picker range defaultvalue="2019-10-10~2019-12-31"></xy-date-picker>
范围选择模式下的value
和date
均为数组
//value ["2019-05-15", "2019-12-26"] //date ["Wed May 15 2019 08:00:00 GMT+0800 (中国标准时间)", "Thu Dec 26 2019 08:00:00 GMT+0800 (中国标准时间)"]
event
当选好日期后,按肯定按钮能够触发change
回调。
<xy-date-picker onchange="console.log(event)"></xy-date-picker>
event:{ detail:{ value, date } }
其余触发方式
date.onchange = function(ev){ console.log(this.value); console.log(this.date); console.log(ev.target.value); console.log(ev.detail.value); console.log(ev.detail.date); } date.addEventListener('change',function(ev){ console.log(this.value); console.log(this.date); console.log(ev.target.value); console.log(ev.detail.value); console.log(ev.detail.date); })
xy-date-picker
内部基于xy-popover
和xy-date-pane
实现。
<xy-popover > <xy-button class="date-btn"></xy-button> <xy-popcon> <xy-date-pane id="color-pane"></xy-date-pane> <div class="pop-footer"> <xy-button id="btn-cancel">取消</xy-button> <xy-button type="primary" id="btn-submit">确认</xy-button> </div> </xy-popcon> </xy-popover>
其中,xy-date-pane
为日期选择面板,可独立使用,若是你只是想要一个日历,可使用这个组件。
<xy-date-pane></xy-date-pane>
事件和属性与xy-date-picker
一致。
整体来讲,xy-date-picker
使用起来仍是很容易的,无需写大量脚本,就像使用一个input
,大部分状况只需知道一个onchange
事件就能够了。
其实xy-ui的组件设计都是靠近原生的,没有那些自创的事件,好比这里的onchange
有些日期组件库就喜欢搞成datechange
什么的,虽然语义很好,可是不够原生,不够统一,用户彻底无感,不看文档彻底不知道下手,反却是原生更具备表明性,规范性,能够说拿到这个组件,往页面上一放,根本无需看api
文档便可上手大部分功能。
目前xy-ui已经完成了大部分常见组件,后续有其余会陆续补充,但愿有须要的小伙伴能够立刻用起来,也但愿可前往github给颗star
,谢谢~