在本人着手开发一个考试系统的过程中,出现了如下一个需求:制作一个倒计时的控件显示在试卷页面上。本文所记录的就是这样的一个过程。

前期工作

对于这个需求,自然我想到的是有没有现成的组件可以直接使用(本着不重复发明轮子的原则)。于是我就在 GitHub 上找寻。确实找到了不少,但是与需求之间的差距还比较大。从零开始写又不太现实(时间摆在那里,加之自己的前端也是刚学,还没有从零开始手撸一个控件的能力),所以在已有组件的基础上进行二次封装便成了一个比较可行的方法(几乎也是唯一解)。遂在 npm 上以 countdown 为关键词搜索,最后找到了 Vue Awesome Countdown 这个组件。这个组件几乎满足了需求,只是它还没有像样的展示形式。所以针对它的二次封装主要就是围绕这个展开。

对于考试倒计时的组件,我希望它有两个功能:在页面上展示剩余时间、在考试结束时自动交卷。接下来的内容就围绕这个展开。

时间显示

要想在页面上进行时间显示。首先需要知道这个倒计时组件是如何保存时间的。翻阅文档得知,保存在组件中的时间是以 timeObj 的形式进行存储(timeObj 的完整格式见下)。对于需求来说,我们只需要其中的 timeObj.htimeObj.mtimeObj.s 即可。

  1. {
  2. "endTime": 1542634411361,
  3. "speed": 1000,
  4. "leftTime": 97019,
  5. "d": "0",
  6. "h": "00",
  7. "m": "01",
  8. "s": "37",
  9. "ms": "019",
  10. "org": {
  11. "d": 0.001134247685185185,
  12. "h": 0.02722194444444444,
  13. "m": 1.6333166666666665,
  14. "s": 37.998999999999995,
  15. "ms": 19
  16. },
  17. "ceil": {
  18. "d": 1,
  19. "h": 1,
  20. "m": 2,
  21. "s": 98
  22. }
  23. }

倒计时的时长,则可以通过后端传过来的考试记录信息进行推算,然后作为一个参数传入,结合网站提供的示例,很快就写出了以下代码:

  1. <template>
  2. <div id="timer-view">
  3. <p class="title">距离考试结束还有</p>
  4. <countdown :end-time="new Date().getTime() + remainingTimes">
  5. <div class="timer" slot="process" slot-scope="{ timeObj }">
  6. {{ `${timeObj.h}:${timeObj.m}:${timeObj.s}` }}
  7. </div>
  8. </countdown>
  9. </div>
  10. </template>
  11. <script>
  12. export default {
  13. name: 'timer',
  14. props: {
  15. remainingTimes: Number
  16. }
  17. }
  18. </script>
  19. <style scoped>
  20. #timer-view {
  21. margin: 15px;
  22. border: solid 1px;
  23. border-radius: 5px;
  24. box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04);
  25. }
  26. .title {
  27. text-align: center;
  28. }
  29. .timer {
  30. text-align: center;
  31. font-family: Arial, Helvetica, sans-serif;
  32. font-size: 50px;
  33. color: red;
  34. font-weight: bold;
  35. }
  36. </style>

计时结束事件

显示的问题解决后,下面要处理的是计时结束后的自动交卷。官方文档中提到了该组件有如下四个事件可以处理:

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 的理解更加深入后会改回事件响应的那套模型。

  1. <!--
  2. 计时器组件
  3. Author: 刘忠燏 (seLiuZhongyu@outlook.com)
  4. -->
  5. <template>
  6. <div id="timer-view">
  7. <p class="title">距离考试结束还有</p>
  8. <countdown :end-time="new Date().getTime() + remainingTimes" @finish="endCallback">
  9. <div class="timer" slot="process" slot-scope="{ timeObj }">
  10. {{ `${timeObj.h}:${timeObj.m}:${timeObj.s}` }}
  11. </div>
  12. </countdown>
  13. </div>
  14. </template>
  15. <script>
  16. export default {
  17. name: 'timer',
  18. props: {
  19. remainingTimes: Number,
  20. endCallback: Function
  21. }
  22. }
  23. </script>
  24. <style scoped>
  25. #timer-view {
  26. margin: 15px;
  27. border: solid 1px;
  28. border-radius: 5px;
  29. box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04);
  30. }
  31. .title {
  32. text-align: center;
  33. }
  34. .timer {
  35. text-align: center;
  36. font-family: Arial, Helvetica, sans-serif;
  37. font-size: 50px;
  38. color: red;
  39. font-weight: bold;
  40. }
  41. </style>

以上就是计时器的完整代码,要使用它,只要传入合适的参数给该组件即可:

  1. <template>
  2. <div>
  3. <timer :remaining-times="remainingTimes" :end-callback="onFinished"></timer>
  4. </div>
  5. </template>
  6. <script>
  7. import Timer from '@/components/Timer'
  8. export default {
  9. name: 'paper-view',
  10. components: {
  11. 'timer': Timer
  12. },
  13. methods: {
  14. onFinished () {
  15. // ...
  16. },
  17. },
  18. computed: {
  19. remainingTimes () {
  20. // ...
  21. }
  22. }
  23. }
  24. </script>
  25. <style>
  26. </style>

总结

通过 这次的组件封装,我对 Vue 的组件有了进一步的认识,也暴露出我在 Vue 的事件模型上了解得还不够深入,在之后的工作中我还需要在这方面继续深入学习。

Vue.js 自定义组件封装实录——基于现有控件的二次封装(以计时器为例)的更多相关文章

  1. Android 自定义View 三板斧之一——继承现有控件

    通常情况下,Android实现自定义控件无非三种方式. Ⅰ.继承现有控件,对其控件的功能进行拓展. Ⅱ.将现有控件进行组合,实现功能更加强大控件. Ⅲ.重写View实现全新的控件 本文重点讨论继承现有 ...

  2. 对百度WebUploader开源上传控件的二次封装,精简前端代码(两句代码搞定上传)

    前言 首先声明一下,我这个是对WebUploader开源上传控件的二次封装,底层还是WebUploader实现的,只是为了更简洁的使用他而已. 下面先介绍一下WebUploader 简介: WebUp ...

  3. 基于vue.js实现远程请求json的select控件

    基本思路 前端把需要的参数类型编码传到后台,后台返回相应的参数列表json,前端利用vue渲染select控件 具体实现 前端代码 <select v-model="template. ...

  4. vue.js自定义组件directives

    自定义指令:以v开头,如:v-mybind. <input v-mybind /> directives:{ mybind:{ bind:function (el) { el.value ...

  5. Vue.js自定义指令的用法与实例

    市面上大多数关于Vue.js自定义指令的文章都在讲语法,很少讲实际的应用场景和用例,以致于即便明白了怎么写,也不知道怎么用.本文不讲语法,就讲自定义指令的用法. 自定义指令是用来操作DOM的.尽管Vu ...

  6. vue中自定义组件(插件)

    vue中自定义组件(插件) 原创 2017年01月04日 22:46:43 标签: 插件 在vue项目中,可以自定义组件像vue-resource一样使用Vue.use()方法来使用,具体实现方法: ...

  7. 【Vue课堂】Vue.js 父子组件之间通信的十种方式

    这篇文章介绍了Vue.js 父子组件之间通信的十种方式,不管是初学者还是已经在用 Vue 的开发者都会有所收获.无可否认,现在无论大厂还是小厂都已经用上了 Vue.js 框架,简单易上手不说,教程详尽 ...

  8. Vue.js多重组件嵌套

    Vue.js多重组件嵌套 Vue.js中提供了非常棒的组件化思想,组件提高了代码的复用性.今天我们来实现一个形如 <app> <app-header></app-head ...

  9. 【Vue.js实战案例】- Vue.js递归组件实现组织架构树和选人功能

    大家好!先上图看看本次案例的整体效果. 浪奔,浪流,万里涛涛江水永不休.如果在jq时代来实这个功能简直有些噩梦了,但是自从前端思想发展到现在的以MVVM为主流的大背景下,来实现一个这样繁杂的功能简直不 ...

随机推荐

  1. javascript 对象的方式解析url地址参数

    看到一个知识点,比如说给一个 url参数,让其解析里面的各个参数,以前我都是通过字符串分割来实现的.但是通过这样的方式比较麻烦,而且操作字符串容易出错.今天看到了一个更有效更快速的方式,就是通过对象来 ...

  2. 数据库-io检测工具sqldeveloper-18.2.0.183.1748-x64 下载链接

    链接:https://pan.baidu.com/s/1R0ujc_9aXdc5O5i1nhNAlA 提取码:o6is

  3. 在ASP.NET MVC中创建自定义模块

    创建模块 module是实现了System.Web.IHttpModule接口的类.该接口定义了两个方法: Init:当模块初始化时被调用,传入的参数为HttpApplication对象,用于注册请求 ...

  4. spring根据beanName获取bean

    spring根据beanName获取bean主要实现: org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean( ...

  5. 来看一下Java中“-”与equeals的区别

    简介: == ==是比较两个变量的值,如果是基本数据类型,那么就是比较的基本数据的大小值 情况一 int a=1; int b=1; System.out.println(a==b); 以上图中:== ...

  6. mysql 多条数据中,分组获取值最大的数据记录

    摘要: 多条纪录中,几个字段相同,但是其中一个或者多个字段不同,则去该字段最大(这里只有一个不同) 源数据: 目的是移除:在同一天中只能存在一天数据,则取审核日期最大,数据库脚本如下: SELECT ...

  7. sudo: /usr/lib/sudo/sudoers.so must be only be writable by owner

    因为某种原因,手动给usr文件夹改了权限,之后我自己这个账户(非root)就不能运行sudo命令,提示"sudo: /usr/lib/sudo/sudoers.so must be only ...

  8. 系统管理员必须知道的PHP安全实践

    Apache web 服务器提供了这种便利 :通过 HTTP 或 HTTPS 协议,访问文件和内容.配置不当的服务器端脚本语言会带来各种各样的问题.所以,使用 PHP 时要小心.以下是 25 个 PH ...

  9. properties文件属性值@Value注解为 java entity属性赋值

    一.使用@Value为 java entity类中的非static属性赋值 举个栗子,一目了然 1.1 properties文件 1.2 servlet.xml 文件增加的配置: 1.2.1 serv ...

  10. log4j和slf4j的区别

    之前在项目中用的日志记录器都是log4j的日志记录器,可是到了公司发现项目要求使用slf4j,于是想着研究一下slf4j的用法. 注意:每次引入Logger的时候注意引入的jar包,因为有Logger ...