服務端時間不須要屢次請求:其由客戶端與服務端的時間差,和當前的客戶端時間比對得出;從而減小了服務端時間的請求次數,提高性能;且防止了瀏覽器切換,程序掛起時,倒計時的失真;serverTime = frontTime - gaphtml
客戶端時間校準:增長了時間校準,防止用戶在倒計時階段修改客戶端時間後,產生的倒計時時間錯誤或者程序假死等;(pc版淘寶倒計時無時間校準功能)ios
模版自定義:使用者可根據須要自定義模版,將根據模版的關鍵字進行時間格式的換算及模版展示邏輯的轉換,甚至能夠跳過特定的時間順序,隨意組合時間特性,以下:git
a、時間隨意組合:
輸入'$Y年,$W周, $m:$s' => 'x年,x周, x:x'es6
b、模版展示邏輯:
輸入'$isBefore{即將開始}' => '即將開始'
or 簡單的「或運算」:輸入'$isBefore||$isIng{倒計時運行中}' => '倒計時運行中'github
c、時間佔位符:正則表達式
佔位符列表:[$Y(年), $M(月), $W(周), $D(日), $h(時), $m(分), $s(秒), $_100ms(100毫秒)];算法
模版替換方法:將取到每類佔位符的數量,從而將數值按照佔位符數量進行填坑;axios
坑位的填充算法:坑位大於數值,數值前補‘0’;坑位小於數值,多餘數值填入第一個坑位;示例以下:promise
``` // 剩餘時間 restTime = { day: 112, minute: 4, second: 15 } // 輸入模版 template = [ '<span>$D</span>', '<span>$D</span>', 'days,' '<span>$m</span>', '<span>$m</span>', ',' '<span>$s</span>', '<span>$s</span>' ].join('') => // 編譯結果 resultTemplate = [ '<span>11</span>', '<span>2</span>', 'days,' '<span>0</span>', '<span>4</span>', ',' '<span>1</span>', '<span>5</span>' ].join('')
```瀏覽器
單元測試:
增長了類方法的單元測試,使用mocha平臺和chai斷言庫,從而下降了開發、調試成本;有些功能開發和驗證,均可經過跑單元測試直接拿到,並不須要將這個頁面跑起來~~
圖2-1 秒殺組件流程圖
流程分析:
a、時間處理:在整個流程中,涉及許多時間的運算,因此將時間轉換成統一的數值,將簡化運算;另輸入的日期可能帶有'-',在ios中沒法識別,轉換函數中作了兼容處理;
b、客戶端時間校準:該流程包括「驗證客戶端時間異常」,及「校準」,兩個環節。第一個環節,經過將當前客戶端時間與上次客戶端時間的差值,與異常閾值進行比對得出,該閾值須要大於倒計時during。第二個環節,經過獲取服務器時間的回調函數給出,該回調函數返回promise對象,其resolve給出{success, serverTime},經過這種封裝,將業務層與組件邏輯進行分離。
c、編譯:
3.一、參數
template: 倒計時渲染的模版,其中包含:
a、展示/顯示命令:$isBefore$isIng$isAfter 和 或運算(||)
如:$isBefore{xxx} 若是狀態爲未開始,則露出xxx,不然不顯示;
($isIng||$isBefore||$isAfter{xxx},支持以上三個命令的或邏輯)
b、佔位符[$Y(年), $M(月), $W(周), $D(日), $h(時), $m(分), $s(秒), $_100ms(100毫秒)]
若是包含$W,則日不大於7!
endSeckillCb: 秒殺結束時的回調。[無參數同perCb]
3.二、調用
import Seckill from './seckill' new Seckill({ endTime: '2018-3-29 11:00:00', startTime: '2018-3-23 15:00:00', getServerTime: () => { return new Promise((resolve, reject) => { axios.get('/common/getNow').then(({data: {success, result}}) => { resolve({ success, serverTime: result }) }) }) } }).init()
UI渲染如圖:
圖3-2-1 默認template渲染圖
3.三、單元測試
命令:mocha --compilers js:babel-core/register ./seckill.test.js
經過使用編譯參數,支持es6語法~
引用:
import Seckill from './seckill' import { expect } from 'chai' const seckillObj = new Seckill() const Util = { _formatDate: seckillObj._formatDate, _currServerTime: seckillObj._currServerTime }
須要留意,再測試類時,須要進行new生成實例對象,再對其方法進行單元測試;另,使用es6的class生成的類,不能枚舉,因此,沒法使用Object.assign方法,直接將對象方法進行拷貝,因此,一些工具函數,需手動複製。
如檢測數據方法是否正確:
describe('expect',function(){ it('checkAFormatData_required',function(){ expect(seckillObj._checkAFormatData.apply(Object.assign({ getServerTime: function() {}, startTime: '2018-11-12 12:12:12', endTime: '2018-11-13 12:12:12', }, Util))).to.be.ok; }); });
經過使用將工具函數手動放入Util對象當中,再傳遞給當前做用域。
而有些狀況下,無需使用實際的函數方法進行測試,可重置依賴的函數,從而下降單元測試的藕合度,提高靈活性和錯誤定位能力,如:
// 編譯模版顯示隱藏邏輯 describe('expect',function(){ it('compileDisplay',function(){ expect(seckillObj._compileDisplay.call({ _isIng: () => true, _isAfter: () => false, _isBefore: () => false }, '$isIng{<span>即將開始</span>}')).to.be.equal('<span>即將開始</span>') }); });
上述測試代碼,若是使用實際的_isIng()等狀態函數時,將須要傳入額外的startTime、endTime、format函數等,這樣依賴一層層往上傳遞,測試將變得複雜。而這些狀態函數、format函數等,都已經通過了自身的單元測試,無需再拿來重測。對於該顯示隱藏的函數單元來講,只須要拿到各狀態的布爾值,即可完成該編譯單元的獨立測試,所以,重置狀態函數,返回須要的狀態布爾值即可。
單元測試結果如圖:
圖3-3-1 單元測試結果圖
3.四、UI渲染個性化
在當前提供的模版邏輯和佔位符沒法知足UI須要的狀況下,可經過使用perCb來實現個性化定製。因爲perCb回調是在每一個倒計時中進行調用,且其調用位置位於template模版掛載以後,所以此時將#seckill的內容置換掉,將實現這一特定的需求。但須要留意的是,perCb中返回的time對象由模版的佔位符計算得出,所以,須要在模版中給出所需的佔位符。代碼以下:
new Seckill({ template: '<p style="display:none">$Y $M $W $D $h $m $s $_100ms</p>', endTime: '2019-4-29 11:00:00', startTime: '2018-3-23 15:00:00', getServerTime: () => { return new Promise((resolve, reject) => { axios.get('/common/getNow').then(({data: {success, result}}) => { resolve({ success, serverTime: result }) }) }) }, perCb: ({time, state}) => { document.querySelector('#seckill').innerHTML = [ '<p style="..."> ' + time.year + ' 年</p>', '<p style="..."> ' + time.month + ' 月</p>', '<p style="..."> ' + time.day + ' 日</p>', '<p style="..."> ' + time.second + ' 秒</p>' ].join('') console.log('per activity', time, state) } }).init()
控制檯捕獲消息及UI渲染結果以下:
圖3-4-1 控制檯捕獲數據圖
圖3-4-2 個性化定製UI渲染圖
tips: a、在輸入的template中,請將DOM元素設置display:none,防止頁面抖動~~
b、在個性化渲染中,須要哪些時間,在模版中制定便可;出如今模版中的佔位符,都將參與計算,不然不參與。