自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

HarmonyOS - 自定義組件之計時器

系統(tǒng) OpenHarmony
前段時間項目中遇到了計時器的功能,項目中的計時器其實只是顯示功能,數(shù)據(jù)全是由設(shè)備上報的。完成項目后,自己做了一個小的計時器組件,在這個過程中也發(fā)現(xiàn)了一些問題。

??想了解更多關(guān)于開源的內(nèi)容,請訪問:??

??51CTO 開源基礎(chǔ)軟件社區(qū)??

??https://ost.51cto.com??

前言

前段時間項目中遇到了計時器的功能,項目中的計時器其實只是顯示功能,數(shù)據(jù)全是由設(shè)備上報的。完成項目后,自己做了一個小的計時器組件,在這個過程中也發(fā)現(xiàn)了一些問題。

效果展示

組件直接傳入以秒為單位的數(shù)據(jù),最終顯示如下效果:

#夏日挑戰(zhàn)賽# HarmonyOS - 自定義組件之計時器-開源基礎(chǔ)軟件社區(qū)

實現(xiàn)原理

1、用setTimeout模擬setInterval的行為

正常情況下,說到計時器首先想到的是使用setInterval,對比setTimeout要去重復(fù)調(diào)用,setInterval很方便就能實現(xiàn),如下代碼:

getTime(time) {
this.countNum = time;
setTimeout(() => {
this.getTime(time --)
}, 1000)
},
setInterval(() => {
this.countNum --
}, 1000)

但為什么要使用setTimeout呢,查下兩個定時器的原理,會發(fā)現(xiàn),創(chuàng)建一個時間間隔為100ms的定時器,setInterval每隔100ms往隊列中添加一個事件;100ms后,添加T1定時器代碼至隊列中,主線程中還有任務(wù)在執(zhí)行,所以等待,some event執(zhí)行結(jié)束后執(zhí)行T1定時器代碼;又過了100ms,T2定時器被添加到隊列中,主線程還在執(zhí)行T1代碼,所以等待;又過了100ms,理論上又要往隊列里推一個定時器代碼,但由于此時T2還在隊列中,所以T3不會被添加,結(jié)果就是此時被跳過;這里我們可以看到,T1定時器執(zhí)行結(jié)束后馬上執(zhí)行了T2代碼,所以并沒有達(dá)到定時器的效果。

#夏日挑戰(zhàn)賽# HarmonyOS - 自定義組件之計時器-開源基礎(chǔ)軟件社區(qū)

綜上所述,setInterval有兩個缺點:

  1. 使用setInterval時,某些間隔會被跳過。
  2. 可能多個定時器會連續(xù)執(zhí)行。

所以,我們要使用setTimeout模擬setInterval,來規(guī)避掉上面的缺點。

2、用Date.now()獲取當(dāng)前時間,規(guī)避瀏覽器退出再進(jìn)來造成的計時誤差

當(dāng)我們在使用計時工具的時候,因為一些原因,將瀏覽器退到后臺,再次進(jìn)來的時候,發(fā)現(xiàn)計時器時間不對,感覺剛才退出去的這段時間,計時器是停止?fàn)顟B(tài)。針對這個問題,查詢會發(fā)現(xiàn),出于節(jié)能的考慮, 部分瀏覽器在進(jìn)入后臺時(或者失去焦點時), 會將 setTimeout 等定時任務(wù)暫停,待用戶回到瀏覽器時, 才會重新激活定時任務(wù)。

說是暫停,實踐操作會發(fā)現(xiàn)其實應(yīng)該說是延遲, 1s 的任務(wù)延遲到 2s, 或者更久,總之,計時器計算掉的時間,比實際過去的時間少。解決這個問題,我們可以使用Date.now()記錄時間,如下,計算兩次計時事件的時間差,來計算每次計時的step。

getTime(time) {
this.countNum = time;
setTimeout(() => {
const nowDate = Date.now()
const diff = Math.floor((nowDate - this.curTime) / 1000)
const step = diff > 1 ? diff : 1 // 頁面退到后臺后計時有偏差,對比時間差,得到計時step
this.curTime = nowDate
this.getTime(time - step)
}, 1000)
},

3、及時清理定時器

這是容易忽略的一點,我們的組件唯一的一個prop屬性就是time,實際的業(yè)務(wù)場景中,可能會有一些操作改變倒計時的時長,所以我們的組件需要監(jiān)聽time值的改變,來做一些初始化操作,這時候你會發(fā)現(xiàn),當(dāng)做了2次初始化操作后,我們的代碼中會同時存在了2個計時器,時間過了1秒后2個計時器同時觸發(fā),對time值做了2次“- 1”操作,所以,我們在初始化時要清除之前的定時器。

getTime(time) {
this.timer && clearTimeout(this.timer) //清除定時器
this.countNum = time;
this.timer = setTimeout(() => {
const nowDate = Date.now()
const diff = Math.floor((nowDate - this.curTime) / 1000)
const step = diff > 1 ? diff : 1 // 頁面退到后臺后計時有偏差,對比時間差,得到計時step
this.curTime = nowDate
this.getTime(time - step)
}, 1000)
},

實現(xiàn)過程

countDown組件hml部分:

<div class="count-down">
<image class="count" src="./count.png"></image>
<div class="countNumCon">
<text class="countNum">
{{countNum}}
</text>
</div>
</div>

countDown組件js部分:

export default {
props: [
'time'
],
data: {
timer: null, //定時器
curTime: 0, //記錄上次操作時間
countNum: '',
},
onInit() {
this.countDown()
this.$watch('time', 'countDown');
},
//將傳入的時間(s)轉(zhuǎn)換成天/小時/分鐘/秒
durationFormatter(time) {
if (!time) return { ss: 0 }
let t = time
const ss = t % 60
t = (t - ss) / 60
if (t < 1) return { ss }
const mm = t % 60
t = (t - mm) / 60
if (t < 1) return { mm, ss }
const hh = t % 24
t = (t - hh) / 24
if (t < 1) return { hh, mm, ss }
const dd = t
return { dd, hh, mm, ss }
},
//處理時間格式
dealTime(time){
return `00${time || ''}`.slice(-2);
},
countDown() {
this.curTime = Date.now()
this.getTime(this.time)
},
//計算時間
getTime(time) {
this.timer && clearTimeout(this.timer)
if (time < 0) {
return
}
const { dd, hh, mm, ss } = this.durationFormatter(time)
this.countNum = `${dd || 0}天 ${this.dealTime(hh)}:${this.dealTime(mm)}:${this.dealTime(ss)}`;
this.timer = setTimeout(() => {
const nowDate = Date.now()
const diff = Math.floor((nowDate - this.curTime) / 1000)
const step = diff > 1 ? diff : 1 // 頁面退到后臺的時候不會計時,對比時間差,大于1s的重置倒計時
this.curTime = nowDate
this.getTime(time - step)
}, 1000)
},
};

countDown組件css部分:

.count-down {
display: flex;
margin-top: 200px;
justify-content: center;
align-items: center;
flex-direction: column;
width: 100%;
height: 50%;
}
.countImg {
width: 200px;
height: 100px;
}
.numContainer {
background-color: black;
height: 57px;
width: 140px;
left: 8px;
top: -80px;
justify-content: center;
border-radius: 7px;
}
.count {
color: white;
font-size: 22px;
font-weight: 500;
}

父組件hml部分:

<element name="countDown" src="../countDown/countDown.hml">
</element>
<div class="container">
<countDown time="{{ leftTime }}">
</countDown>
</div>

父組件js部分:

export default {
data: {
leftTime: 100,
},
};

總結(jié)

這個計時器組件就是對日常工作的發(fā)散,作為一個鴻蒙小白,順便做一個小小的練習(xí)。

??想了解更多關(guān)于開源的內(nèi)容,請訪問:??

??51CTO 開源基礎(chǔ)軟件社區(qū)??

??https://ost.51cto.com??。

責(zé)任編輯:jianghua 來源: 鴻蒙社區(qū)
相關(guān)推薦

2022-07-06 20:24:08

ArkUI計時組件

2022-04-24 15:17:56

鴻蒙操作系統(tǒng)

2021-11-01 10:21:36

鴻蒙HarmonyOS應(yīng)用

2022-07-12 16:56:48

自定義組件鴻蒙

2021-09-15 10:19:15

鴻蒙HarmonyOS應(yīng)用

2022-06-30 14:02:07

鴻蒙開發(fā)消息彈窗組件

2022-07-15 16:45:35

slider滑塊組件鴻蒙

2011-05-31 16:50:35

Android 線程

2012-05-08 13:58:37

SharePoint

2021-11-22 10:00:33

鴻蒙HarmonyOS應(yīng)用

2021-12-24 15:46:23

鴻蒙HarmonyOS應(yīng)用

2022-02-16 16:09:12

鴻蒙游戲操作系統(tǒng)

2023-02-20 15:20:43

啟動頁組件鴻蒙

2022-10-25 15:12:24

自定義組件鴻蒙

2022-10-26 15:54:46

canvas組件鴻蒙

2021-02-20 12:34:53

鴻蒙HarmonyOS應(yīng)用開發(fā)

2009-06-25 14:53:35

自定義UI組件JSF框架

2022-12-07 08:56:27

SpringMVC核心組件

2022-03-01 16:09:06

OpenHarmon鴻蒙單選組件

2023-01-03 07:40:27

自定義滑塊組件
點贊
收藏

51CTO技術(shù)棧公眾號