徒手擼UI之TimePicker

QingUI是一個UI組件庫

目前擁有的組件:DatePicker, TimePicker, Paginator, Tree, Cascader, Checkbox, Radio, Switch, InputNumber, Input

ES6語法編寫,無依賴

原生模塊化,Chrome63以上支持,請開啓靜態服務器預覽效果, 靜態服務器傳送門

採用CSS變量配置樣式

辛苦造輪子,歡迎來github倉庫star: https://github.com/veedrin/qing

四月份找工做,求內推,座標深圳

寫在前面

去年年末項目中嘗試着寫過一個分頁的Angular組件,而後就有了寫QingUI的想法javascript

過程仍是很是有意思的java

接下來我會用幾篇文章分別介紹每一個組件的大概思路,請你們耐心等待git

這一篇介紹TimePicker日期選擇器github

最重要的,求star,求fork,求內推數組

QingUI

少廢話,先上圖

img failed

當前時間

介紹DatePicker的文章寫的時候已經凌晨了,畢竟那天commit了50屢次,因此有點草率,這回我儘可能寫的清楚一點緩存

初始加載TimePicker的時候確定顯示當前的時間,因此咱們首先要獲取當前的時間服務器

當前時間好說,只是ES6提供瞭解構賦值正好能夠在這裏派上用場模塊化

直接返回一個數組,須要的時候一次性賦值就行了函數

若是不須要這麼多,沒問題,ES6不只能夠批發,還能夠零售,貼不貼心!性能

爲何秒不直接賦值呢?由於我以爲不多有場景咱們須要精確到秒,還不如初始直接給個0,省的別人點一下,他要精確到秒是他的事

constructor() {
    [this.H, this.M, ] = this.nowTime();
    this.S = 0;
}

nowTime() {
    const date = new Date();
    return [date.getHours(), date.getMinutes(), date.getSeconds()];
}

當用戶選擇的時候,選中的就會高亮,以前的高亮會取消

咱們能夠粗暴一點,每次點擊都運行一個for循環,找到高亮,取消高亮,場子清完之後再將當前選中的高亮

不過這樣性能確定是很差的

若是我把選中的時間緩存起來

每次點擊的時候我還記得上次高亮的在哪,直接處理它就行了,少了一個for循環是否是好多了

不過要注意,每次點擊都要把新值緩存,它就是個跟屁蟲,可不能掉隊

constructor() {
    [this.oldH, this.oldM, this.oldS] = [this.H, this.M, this.S];
}

切換

時鐘、分鐘、秒鐘,總共有三個面板,因此我設置三個按鈕,時間格動態渲染

假如用戶點擊時鐘按鈕,他要怎麼辨別剛纔點的是哪一個按鈕呢?

下意識的,咱們會想到,當前活躍的,咱們就給它置灰,以來做區分,二來省的用戶無聊老在一個地方點來點去形成重複渲染

我之前也有過一點經驗,就是buttondisabled屬性並非經過true和false來控制的

真正控制它是否置灰的,是有沒有這個屬性

我以爲這個設計...

因此咱們寫一個控制置灰的函數,一樣,oldDisabled是用來緩存的

ableAndDisableEvent(ableNode) {
    if (this.oldDisabled) {
        this.oldDisabled.removeAttribute('disabled');
    }
    ableNode.setAttribute('disabled', '');
    this.oldDisabled = ableNode;
}

有時候咱們有這樣的需求,雖然點擊事件是響應用戶操做的,但偶爾咱們本身也但願觸發一下事件

用戶能夠觸發點擊事件,那麼程序能夠嗎?

實際上是能夠的,.click(),就這麼簡單

說實話這個我也是第一次見,多是我比較孤陋寡聞吧...

this.oldDisabled.click();

轉數字

當咱們點擊時,獲取到的innerHTML其實是一個字符串

我但願在入口把關,保證this.H; this.M; this.S;都是數字類型

因而咱們就要把字符串類型的數字轉成真數字,這倒不難

我曾經測過幾種字符串類型的數字轉成真數字的方法,固然,我說的是正整數

  • parseInt()
  • parseFlout()
  • Number()
  • Math.floor()
  • num - 0

性能確定是num - 0最好,可是這樣並非特別正規

除此以外,性能最好的是parseInt()parseFlout()要考慮小數位,Number()估計是內部的類型轉換比較複雜

除了語義化並非特別好以外,我日常都喜歡用parseInt()

但這不是重點

重點是ES6在Number下面也掛載了該方法,window.parseInt()Number.parseInt()都是能夠的,爲何這樣作呢?

由於JS的全局對象window實在是太複雜了,它不只是全局對象,仍是窗口對象,連全部的全局變量都掛在它下面

因此W3C但願改變這個現狀,儘可能減小甚至取消window下面的屬性

這也是爲何在ES6模塊內,指向全局的this等於undefined

因此,若是兼容性容許的話,儘可能用Number.parseInt()代替window.parseInt(),爲美妙的JS盡一份力

Everything Based On JavaScript就不遠了吧

格式化

比較正規的時間表盤都會顯示兩位數,好比3點20分,會寫成03: 20

因此咱們也須要一個兩位數的格式化函數

爲何須要String(num).length === 1這個判斷條件?

由於有時傳進來的參數已經格式化過了,而它實際上又小於10,因此須要過濾掉它們

twoDigitsFormat(num) {
    if (String(num).length === 1 && num < 10) {
        num = `0${num}`;
    }
    return num;
}

而後我再用一個漏斗函數把變化收集起來,統一更新

timeChangeEvent(hour, minute, second) {
    hour ? this.H = hour : '';
    minute ? this.M = minute : '';
    second ? this.S = second : '';
    this.$view.innerHTML = this.timeFormat(this.H, this.M, this.S);
}

至於顯示成最終的時間格式,咱們有它

timeFormat(hour = 0, minute = 0, second = 0) {
    hour = this.twoDigitsFormat(hour);
    minute = this.twoDigitsFormat(minute);
    second = this.twoDigitsFormat(second);
    return `${hour} : ${minute} : ${second}`;
}

寫在後面

首先,這個時間選擇器確實很差看,我未來可能會重構

而後,時間選擇器也確實比較簡單,比日期選擇器代碼少多了

不過仍是能夠本身嘗試着本身寫一個,一切都在細節裏

下一篇文章介紹Paginator,敬請期待

最後,求star,求fork,求內推

QingUI
相關文章
相關標籤/搜索