UNPKG

antd-mini

Version:

antd-mini 是支付宝小程序 UI 组件库,遵循 Ant Design 规范。

186 lines (164 loc) 5.65 kB
import dayjs from 'dayjs'; import duration from 'dayjs/plugin/duration'; import { Component, getValueFromProps, triggerEvent, triggerEventOnly, } from '../_util/simply'; import { CountdownDefaultProps } from './props'; dayjs.extend(duration); Component({ props: CountdownDefaultProps, data: { countdownDay: null, // 注意这些倒计时相关的都应该是字符串 countdownHour: null, // 倒计时小时 注意都用字符串,避免0被判false的问题 countdownMin: null, // 倒计时分钟 countdownSec: null, // 倒计时秒 showDecisecond: true, // 倒计时结束时不展示秒后一位(厘秒) }, methods: { init() { const [ countdownStartTime, countdownEndTime, countdownType, time, autoShowDay, ] = getValueFromProps(this, [ 'countdownStartTime', 'countdownEndTime', 'countdownType', 'time', 'autoShowDay', ]); const timeNum = isNaN(Number(time)) ? 0 : Number(time); const defaultEndTime = +new Date() + timeNum * 1000; const currentTimeStr = `${countdownStartTime || +new Date()}`; const endTimeStr = `${countdownEndTime || defaultEndTime}`; // 如果服务端给的是秒级别的时间戳,自动补3个0转成毫秒的 const finalCurrentTimeStr = `${currentTimeStr}${ currentTimeStr.length === 10 ? '000' : '' }`; const finalEndTimeStr = `${endTimeStr}${ endTimeStr.length === 10 ? '000' : '' }`; const finalStartTime = parseInt(finalCurrentTimeStr, 10); const finalEndTime = parseInt(finalEndTimeStr, 10); this.setData({ showDay: autoShowDay ? this.data.countdownDay !== '0' : true, }); this.countdown(finalStartTime, finalEndTime, (remainTime) => { if (remainTime < 1) { // 小于1s了,说明倒计时该结束了 triggerEventOnly(this, 'countdownFinish'); this.setData({ showDecisecond: false, }); } const durationTime = dayjs.duration(remainTime); const day = Math.floor(durationTime.asDays()).toString(); let hour = ''; if (countdownType === 'day') { hour = durationTime.format('HH'); } else { const hoursNum = Math.floor(durationTime.asHours()); hour = `${hoursNum < 10 ? '0' : ''}${hoursNum > 0 ? hoursNum : '0'}`; } const min = durationTime.format('mm'); const sec = durationTime.format('ss'); this.setData({ countdownDay: day, countdownHour: hour, countdownMin: min, countdownSec: sec, }); triggerEvent(this, 'countdownChange', { remainTime, day, hour, min, sec, }); }); }, countdown( startTimestamp: number, endTimestamp: number, callback: (remainingTime: number) => void ) { // if (isNaN(startTimestamp) || isNaN(endTimestamp)) { // return; // } const currentTime = Date.now(); // 当前时间戳 if ( currentTime - Math.round(startTimestamp) < 10000 && Math.round(startTimestamp) - currentTime < 10000 ) { // 如果服务端下发的startTime时间戳和本机的时间戳相差10s以内,以本地时间戳为准 const getRemainingTime = (): number => { // 本地时间戳与服务端时间戳差距在10s以内都属于正常的,可以直接用本地时间。 let remainingTime; const newCurrentTime = +new Date(); // 判断是否到达结束时间 if (newCurrentTime >= endTimestamp) { remainingTime = 0; } else { remainingTime = endTimestamp - newCurrentTime; } return remainingTime; }; const updateCountdown = () => { const remainingTime = getRemainingTime(); // 调用setData方法更新UI callback(remainingTime); if (remainingTime > 0) { // 若还有剩余时间,延迟1秒后递归调用自身 this.timer = setTimeout(updateCountdown, 1000); } }; // 预先调一次 const remainingTime = getRemainingTime(); callback(remainingTime); if (remainingTime === 0) { // 如果第一次就是0,可以直接停了 return; } // 初始化倒计时 updateCountdown(); } else { // 否则以服务端时间为准,直接算出当前剩余时间,按秒循环即可 const remainingTime = endTimestamp - startTimestamp; const totalCount = Math.round(remainingTime / 1000); let count = 0; // 立刻调一次 callback(remainingTime - count * 1000); // 每秒调一次,循环count次 this.intervalId = setInterval(() => { if (count >= totalCount) { clearInterval(this.intervalId); } else { count++; // console.log('111111', remainingTime, count, remainingTime - count * 1000) callback(remainingTime - count * 1000); } }, 1000); } }, }, onInit() { this.init(); }, didUnmount() { clearInterval(this.intervalId); clearTimeout(this.timer); }, didUpdate(prevProps) { const autoShowDay = getValueFromProps(this, 'autoShowDay'); if (prevProps.autoShowDay !== autoShowDay) { this.setData({ showDay: autoShowDay ? this.data.countdownDay !== '0' : true, }); } }, });