Vue.js 自定義組件封裝實錄——基於現有控件的二次封裝(以計時器爲例)

在本人着手開發一個考試系統的過程當中,出現了以下一個需求:製做一個倒計時的控件顯示在試卷頁面上。本文所記錄的就是這樣的一個過程。前端

前期工做

對於這個需求,天然我想到的是有沒有現成的組件能夠直接使用(本着不重複發明輪子的原則)。因而我就在 GitHub 上找尋。確實找到了很多,可是與需求之間的差距還比較大。從零開始寫又不太現實(時間擺在那裏,加之本身的前端也是剛學,尚未從零開始手擼一個控件的能力),因此在已有組件的基礎上進行二次封裝便成了一個比較可行的方法(幾乎也是惟一解)。遂在 npm 上以 countdown 爲關鍵詞搜索,最後找到了 Vue Awesome Countdown 這個組件。這個組件幾乎知足了需求,只是它尚未像樣的展現形式。因此針對它的二次封裝主要就是圍繞這個展開。vue

對於考試倒計時的組件,我但願它有兩個功能:在頁面上展現剩餘時間、在考試結束時自動交卷。接下來的內容就圍繞這個展開。npm

時間顯示

要想在頁面上進行時間顯示。首先須要知道這個倒計時組件是如何保存時間的。翻閱文檔得知,保存在組件中的時間是以 timeObj 的形式進行存儲(timeObj 的完整格式見下)。對於需求來講,咱們只須要其中的 timeObj.htimeObj.mtimeObj.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 的事件模型上了解得還不夠深刻,在以後的工做中我還須要在這方面繼續深刻學習。網站

相關文章
相關標籤/搜索