怎樣實(shí)現(xiàn)一個(gè)datePicker(日期選擇)組件

百度前端技術(shù)學(xué)院上有一個(gè)任務(wù)硼被,要實(shí)現(xiàn)一個(gè)日期選擇組件允粤,本文由此而來~

  1. 看看需求
  • 組件默認(rèn)一直呈顯示狀態(tài)
  • 通過某種方式選擇年暖庄、月,選擇了年月后祥楣,日期列表做相應(yīng)切換
  • 通過單擊某個(gè)具體的日期進(jìn)行日期選擇
  • 組件初始化時(shí)开财,可配置可選日期的上下限∥笸剩可選日期和不可選日期需要有樣式上的區(qū)別
  • 提供設(shè)定日期的接口床未,指定具體日期,日歷面板相應(yīng)日期選中
  • 日期選擇面板默認(rèn)隱藏振坚,會(huì)顯示一個(gè)日期顯示框和一個(gè)按鈕,點(diǎn)擊這兩個(gè)部分斋扰,會(huì)浮出日歷面板渡八。再點(diǎn)擊則隱藏。
  • 點(diǎn)擊選擇具體日期后传货,面板隱藏屎鳍,日期顯示框中顯示選取的日期
  • 增加一個(gè)接口,用于當(dāng)用戶選擇日期后的回調(diào)處理
  • 增加一個(gè)參數(shù)及相應(yīng)接口方法问裕,來決定這個(gè)日歷組件是選擇具體某天日期逮壁,還是選擇一個(gè)時(shí)間段
  • 當(dāng)設(shè)置為選擇時(shí)間段時(shí),需要在日歷面板上點(diǎn)擊兩個(gè)日期來完成一次選擇粮宛,兩個(gè)日期中窥淆,較早的為起始時(shí)間,較晚的為結(jié)束時(shí)間巍杈,選擇的時(shí)間段用特殊樣式標(biāo)示
  • 增加參數(shù)及響應(yīng)接口方法忧饭,允許設(shè)置時(shí)間段選擇的最小或最大跨度,并提供當(dāng)不滿足跨度設(shè)置時(shí)的默認(rèn)處理及回調(diào)函數(shù)接口
  • 在彈出的日期段選擇面板中增加確認(rèn)和取消按鈕

先完成一個(gè)組件的基本結(jié)構(gòu)

    (function(window,document){
       function Calendar(options){
          //傳入配置的中的參數(shù)
          this.init();
       } 
       Calendar.prototype={
            init:function(){
               this.createDom();
               this.loadCss();
               this.cacheDom();
               this.bindEvents();
               this.render();
            },
            loadCss:function(){
               // 把組件所需的樣式表動(dòng)態(tài)加載進(jìn)來
            },
            createDom:function(){
               // 創(chuàng)建dom對(duì)象或者創(chuàng)建html片段或者創(chuàng)建template
            },
            cacheDom:function(){
               // 存儲(chǔ)dom 對(duì)象
            },
            bindEvents:function(){
               //事件綁定
            },
            render:function(){
              //渲染函數(shù)筷畦,更新數(shù)據(jù)或樣式
            }
       }
       window.Calendar=Calendar;//把組件對(duì)象綁定到全局
    }(window,document));

通常我寫組件時(shí)的基本結(jié)構(gòu)如上词裤,你可以根據(jù)組件的需要或者自己習(xí)慣進(jìn)行編寫。然后就可以在html里面添加以下的代碼就可以調(diào)用我們的組件了鳖宾,

<script src='calendar.js></script>
<script type='text/javascript'>
   var a=new Calendar({
      // 各種配置
      /* 類似于 id:'myCalendar'
         onSelected:function(){
                    alert('hello');
        }
     */
   });
</script>

下面再看一下我們的需求吼砂,我們來一 一分析

需求也不是很多嘛,手動(dòng)斜眼~
先上圖鼎文,根據(jù)圖再慢慢分析

概要圖
概要圖

其實(shí)我們看了需求之后渔肩,每個(gè)人都會(huì)有一個(gè)大概的思路,下面說一下我的思路
首先拇惋,要實(shí)現(xiàn)一個(gè)日期選擇器赖瞒,最重要的就是要有一個(gè)日歷女揭,根據(jù)不同的年份和月份,日期面板上回顯示每一天和對(duì)應(yīng)的周幾~
其實(shí)實(shí)現(xiàn)這一點(diǎn)的話就兩點(diǎn)

  • 第一栏饮,要根據(jù)年份和月份算出每月有多少天
  • 第二吧兔,要計(jì)算出每月的第一天(1號(hào))是周幾
    偽代碼如下:
 /**
     * @param  {string} year  年份
     * @param  {string} month 月份
     * @param  {string} day   號(hào)
     * @return {object}  message
     * message{
     * year   年份
     * month  月份
     * monthLen  那個(gè)月的天數(shù)
     * whichDay  1號(hào)是周幾
     * day       號(hào)
     * }    
     */
     function calculate(year,month,day){
                var date=year+'/'+month+'/'+'1';
                var whichDay=new Date(date).getDay();
              var message={
                    year:year,
                    month:month,
                    monthLen:new Date(year,month,0).getDate(),
                    whichDay:whichDay,
                    day:day
              };
              return message;
     },

我想看完代碼之后大家應(yīng)該比較疑惑的是獲取每個(gè)月天數(shù)的那句代碼,這個(gè)比較優(yōu)雅的做法是從這里看到的,
注意:在Date對(duì)象里month為0代表的是1月份袍嬉,month為5代表6月份境蔼,所以我new Date(year,5,0)代表的六月份的第0天,即5月份的最后一天伺通,所以還可以用getDate()獲取5月份的長(zhǎng)度,getDate方法是返回指定日期對(duì)象的月份中的第幾天(1-31)箍土。
所以當(dāng)我們點(diǎn)擊了月份加減/年份加減的按鈕時(shí),向calculate函數(shù)傳入變化后的year,month參數(shù)罐监,然后進(jìn)行渲染吴藻,日歷面板改變

其次,”選擇時(shí)間段并且另處于開始時(shí)間和結(jié)束時(shí)間之間的日期添加特殊的樣式“這一點(diǎn)也是花了不少時(shí)間來寫弓柱,
偽代碼如下:

// 初始化
var firstDate,secondDate=[0,0,0];
//點(diǎn)擊日歷面板上的日期的點(diǎn)擊事件的執(zhí)行函數(shù)的片段沟堡,每當(dāng)點(diǎn)擊事件被觸發(fā),就會(huì)執(zhí)行該片段

if(self.isSelectRange){
             var date=[self.year.innerHTML,self.month.innerHTML,ele.innerHTML];            
             if(self.firstDate[0]===0){// 
                if(self.secondDate[0]===0){//兩個(gè)日期都沒有被設(shè)置
                     self.firstDate=date;
                }else{//firstDate沒有被設(shè)置矢空,secondDate已經(jīng)被設(shè)置,
                     
                }
             }else{
                if(self.secondDate[0]===0){//firstDate已經(jīng)設(shè)置航罗,
                    self.secondDate=date;
                    if(compareDate(self.firstDate.join('/'),self.secondDate.join('/'))){//如果第一個(gè)選擇的日期大于第二次選擇的日期,進(jìn)行交換
                        self.firstDate=[self.secondDate,self.secondDate=self.firstDate][0];
                    } 
                }else{//兩個(gè)日期都已經(jīng)被設(shè)置,已經(jīng)選擇了兩個(gè)元素屁药,再次選擇則都
                   self.secondDate=[0,0,0];
                   self.firstDate=date;
                   self.clearDayInRangeStyle();
                }
             }
             self.day.innerHTML=ele.innerHTML;
             self.render();

firstDate粥血,secondDate分別代表開始時(shí)間和結(jié)束時(shí)間。每次觸發(fā)日期的點(diǎn)擊事件時(shí)酿箭,就會(huì)執(zhí)行以上的代碼片段复亏,對(duì)firstDate和secondDate進(jìn)行更改,這樣的話缭嫡,無論是我對(duì)日歷面板進(jìn)行更新或者對(duì)開始時(shí)間和結(jié)束時(shí)間之間的日期顯示不同的樣式蜓耻,都可以通過firstDate和secondDate來實(shí)現(xiàn)。

顯示不同的樣式就判斷日期是否在開始時(shí)間和結(jié)束時(shí)間之間械巡,每次重新render的時(shí)候就給選擇過的firstDate和secondDate添加樣式刹淌。

包括計(jì)算開始時(shí)間和結(jié)束時(shí)間之間的跨度是否在設(shè)定的跨度內(nèi),我們點(diǎn)擊按鈕后進(jìn)行判斷讥耗。
最后有勾,看看render函數(shù)怎么實(shí)現(xiàn)
關(guān)于render函數(shù),有以下幾點(diǎn)需要注意:

  • 清除日歷面板上的所有內(nèi)容和樣式古程,樣式通過清除每個(gè)單元格上的類實(shí)現(xiàn)
  • 根據(jù)每月1號(hào)是周幾和每月的長(zhǎng)度生成每月的日歷
  • 根據(jù)記錄的fisrtDate和secondDate來顯示已經(jīng)選擇過的選擇的樣式

以上大概是我的思路蔼卡,我也實(shí)現(xiàn)了一個(gè)組件,有興趣的朋友可以點(diǎn)這里挣磨,歡迎找bug~
ps:文筆還是不行雇逞,文章寫的好爛荤懂。。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末塘砸,一起剝皮案震驚了整個(gè)濱河市节仿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌掉蔬,老刑警劉巖廊宪,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異女轿,居然都是意外死亡箭启,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門蛉迹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來傅寡,“玉大人,你說我怎么就攤上這事北救〖霾伲” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵扭倾,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我挽绩,道長(zhǎng)膛壹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任唉堪,我火速辦了婚禮模聋,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘唠亚。我一直安慰自己链方,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布灶搜。 她就那樣靜靜地躺著祟蚀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪割卖。 梳的紋絲不亂的頭發(fā)上前酿,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音鹏溯,去河邊找鬼罢维。 笑死,一個(gè)胖子當(dāng)著我的面吹牛丙挽,可吹牛的內(nèi)容都是我干的肺孵。 我是一名探鬼主播匀借,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼平窘!你這毒婦竟也來了吓肋?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤初婆,失蹤者是張志新(化名)和其女友劉穎蓬坡,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體磅叛,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡屑咳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了弊琴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片兆龙。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖敲董,靈堂內(nèi)的尸體忽然破棺而出紫皇,到底是詐尸還是另有隱情,我是刑警寧澤腋寨,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布聪铺,位于F島的核電站,受9級(jí)特大地震影響萄窜,放射性物質(zhì)發(fā)生泄漏铃剔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一查刻、第九天 我趴在偏房一處隱蔽的房頂上張望键兜。 院中可真熱鬧,春花似錦穗泵、人聲如沸普气。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)现诀。三九已至,卻和暖如春履肃,著一層夾襖步出監(jiān)牢的瞬間赶盔,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工榆浓, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留于未,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像烘浦,于是被迫代替她去往敵國(guó)和親抖坪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,139評(píng)論 25 707
  • 內(nèi)容抽屜菜單ListViewWebViewSwitchButton按鈕點(diǎn)贊按鈕進(jìn)度條TabLayout圖標(biāo)下拉刷新...
    皇小弟閱讀 46,761評(píng)論 22 665
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)闷叉、插件擦俐、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,103評(píng)論 4 62
  • 手機(jī)上的一個(gè)抓娃娃小游戲原型,有設(shè)定抓住的幾率握侧,這里就不做判斷了蚯瞧,只實(shí)現(xiàn)抓取的效果! HTML JS CSS
    fixppy閱讀 750評(píng)論 0 2
  • 概覽與綜述 基本形式 解釋: DOCTYPE 聲明了文檔類型 位于標(biāo)簽 描述了文檔附加信息 位于標(biāo)簽 ...
    熊白白閱讀 331評(píng)論 0 2