在本人着手开发一个考试系统的过程当中,出现了以下一个需求:制做一个倒计时的控件显示在试卷页面上。本文所记录的就是这样的一个过程。前端
对于这个需求,天然我想到的是有没有现成的组件能够直接使用(本着不重复发明轮子的原则)。因而我就在 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 的事件模型上了解得还不够深刻,在以后的工做中我还须要在这方面继续深刻学习。网站