純手工打造的日期選擇器 xy-date-picker 原理與使用

最近花了差很少快兩週的空閒時間打造了一個日期選擇組件,先看看效果javascript

能夠說是一個常常要用到,不多人會主動去實現的一個組件,畢竟實現起來仍是要必定的時間的,因此平時工做之餘就能夠試着打造一些基礎組件庫,既能夠鍛鍊本身的基本功,又能夠爲公司爲社區作貢獻~html

先看一下用法吧,推薦查看文檔,能夠實時交互java

安裝使用

一般有如下幾種安裝方式git

  • npm
npm i xy-ui
複製代碼
  • cdn
<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拷貝源碼。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(默認)、monthyear,分別實現日期選擇器、月選擇器、年選擇器。

<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,能夠取值toprightbottomlefttoplefttoprightrighttoprightbottombottomleftbottomrightlefttopleftbottom。當你的日期選擇器位於屏幕邊緣時能夠調整該屬性。

<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>
複製代碼

範圍選擇模式下的valuedate均爲數組

//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-popoverxy-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,謝謝~

相關文章
相關標籤/搜索