在本人着手開發一個考試系統的過程當中,出現了以下一個需求:製做一個倒計時的控件顯示在試卷頁面上。本文所記錄的就是這樣的一個過程。前端
對於這個需求,天然我想到的是有沒有現成的組件能夠直接使用(本着不重複發明輪子的原則)。因而我就在 GitHub 上找尋。確實找到了很多,可是與需求之間的差距還比較大。從零開始寫又不太現實(時間擺在那裏,加之本身的前端也是剛學,尚未從零開始手擼一個控件的能力),因此在已有組件的基礎上進行二次封裝便成了一個比較可行的方法(幾乎也是惟一解)。遂在 npm 上以 countdown 爲關鍵詞搜索,最後找到了 Vue Awesome Countdown 這個組件。這個組件幾乎知足了需求,只是它尚未像樣的展現形式。因此針對它的二次封裝主要就是圍繞這個展開。vue
對於考試倒計時的組件,我但願它有兩個功能:在頁面上展現剩餘時間、在考試結束時自動交卷。接下來的內容就圍繞這個展開。npm
要想在頁面上進行時間顯示。首先須要知道這個倒計時組件是如何保存時間的。翻閱文檔得知,保存在組件中的時間是以 timeObj
的形式進行存儲(timeObj
的完整格式見下)。對於需求來講,咱們只須要其中的 timeObj.h
、timeObj.m
、timeObj.s
便可。json
{ "endTime": 1542634411361, "speed": 1000, "leftTime": 97019, "d": "0", "h": "00", "m": "01", "s": "37", "ms": "019", "org": { "d": 0.001134247685185185, "h": 0.02722194444444444, "m": 1.6333166666666665, "s": 37.998999999999995, "ms": 19 }, "ceil": { "d": 1, "h": 1, "m": 2, "s": 98 } }
倒計時的時長,則能夠經過後端傳過來的考試記錄信息進行推算,而後做爲一個參數傳入,結合網站提供的示例,很快就寫出瞭如下代碼:後端
<template> <div id="timer-view"> <p class="title">距離考試結束還有</p> <countdown :end-time="new Date().getTime() + remainingTimes"> <div class="timer" slot="process" slot-scope="{ timeObj }"> {{ `${timeObj.h}:${timeObj.m}:${timeObj.s}` }} </div> </countdown> </div> </template> <script> export default { name: 'timer', props: { remainingTimes: Number } } </script> <style scoped> #timer-view { margin: 15px; border: solid 1px; border-radius: 5px; box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04); } .title { text-align: center; } .timer { text-align: center; font-family: Arial, Helvetica, sans-serif; font-size: 50px; color: red; font-weight: bold; } </style>
顯示的問題解決後,下面要處理的是計時結束後的自動交卷。官方文檔中提到了該組件有以下四個事件能夠處理:ide
Event | Explain | Parameters |
---|---|---|
start | Functions executed at the beginning of countdown | vm |
process | Function executed when countdown is performed | vm |
stop | Function executed when countdown stops | vm |
finish | Function executed when countdown finished | vm |
不難看出,對於需求來講,能夠響應它的 finish
事件完成這一功能。這裏限於本人對 Vue 的事件響應瞭解還不是很透徹,這裏採用了一個比較麻煩的手法處理該問題(將響應 finish
事件的函數做爲參數傳入組件,而後對應的部分直接寫 @finish="傳入的參數"
)。以後對 Vue 的理解更加深刻後會改回事件響應的那套模型。函數
<!-- 計時器組件 Author: 劉忠燏 (seLiuZhongyu@outlook.com) --> <template> <div id="timer-view"> <p class="title">距離考試結束還有</p> <countdown :end-time="new Date().getTime() + remainingTimes" @finish="endCallback"> <div class="timer" slot="process" slot-scope="{ timeObj }"> {{ `${timeObj.h}:${timeObj.m}:${timeObj.s}` }} </div> </countdown> </div> </template> <script> export default { name: 'timer', props: { remainingTimes: Number, endCallback: Function } } </script> <style scoped> #timer-view { margin: 15px; border: solid 1px; border-radius: 5px; box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04); } .title { text-align: center; } .timer { text-align: center; font-family: Arial, Helvetica, sans-serif; font-size: 50px; color: red; font-weight: bold; } </style>
以上就是計時器的完整代碼,要使用它,只要傳入合適的參數給該組件便可:學習
<template> <div> <timer :remaining-times="remainingTimes" :end-callback="onFinished"></timer> </div> </template> <script> import Timer from '@/components/Timer' export default { name: 'paper-view', components: { 'timer': Timer }, methods: { onFinished () { // ... }, }, computed: { remainingTimes () { // ... } } } </script> <style> </style>
經過 此次的組件封裝,我對 Vue 的組件有了進一步的認識,也暴露出我在 Vue 的事件模型上了解得還不夠深刻,在以後的工做中我還須要在這方面繼續深刻學習。網站