最近花了差很少快兩週的空閒時間打造了一個日期選擇組件,先看看效果javascript
能夠說是一個常常要用到,不多人會主動去實現的一個組件,畢竟實現起來仍是要必定的時間的,因此平時工做之餘就能夠試着打造一些基礎組件庫,既能夠鍛鍊本身的基本功,又能夠爲公司爲社區作貢獻~html
先看一下用法吧,推薦查看文檔,能夠實時交互java
一般有如下幾種安裝方式git
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拷貝源碼。github
使用npm
<xy-date-picker></xy-date-picker>
複製代碼
一個標籤的事,開箱即用,多是使用起來最方便的日期選擇器了。api
這裏簡單介紹一下日期的生成原理數組
要實現一個月的展現,通常分爲三個部分,分別爲前一個月,當前月,下一個月bash
爲此,咱們須要知道ui
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
,謝謝~