| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 | <template>	<view class="u-count-down">		<slot>			<text class="u-count-down__text">{{ formattedTime }}</text>		</slot>	</view></template><script>	import props from './props.js';	import {		isSameSecond,		parseFormat,		parseTimeData	} from './utils';	/**	 * u-count-down 倒计时	 * @description 该组件一般使用于某个活动的截止时间上,通过数字的变化,给用户明确的时间感受,提示用户进行某一个行为操作。	 * @tutorial https://uviewui.com/components/countDown.html	 * @property {String | Number}	time		倒计时时长,单位ms (默认 0 )	 * @property {String}			format		时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒  (默认 'HH:mm:ss' )	 * @property {Boolean}			autoStart	是否自动开始倒计时 (默认 true )	 * @property {Boolean}			millisecond	是否展示毫秒倒计时 (默认 false )	 * @event {Function} finish 倒计时结束时触发 	 * @event {Function} change 倒计时变化时触发 	 * @event {Function} start	开始倒计时	 * @event {Function} pause	暂停倒计时 	 * @event {Function} reset	重设倒计时,若 auto-start 为 true,重设后会自动开始倒计时 	 * @example <u-count-down :time="time"></u-count-down>	 */	export default {		name: 'u-count-down',		mixins: [uni.$u.mpMixin, uni.$u.mixin, props],		data() {			return {				timer: null,				// 各单位(天,时,分等)剩余时间				timeData: parseTimeData(0),				// 格式化后的时间,如"03:23:21"				formattedTime: '0',				// 倒计时是否正在进行中				runing: false,				endTime: 0, // 结束的毫秒时间戳				remainTime: 0, // 剩余的毫秒时间			}		},		watch: {			time(n) {				this.reset()			}		},		mounted() {			this.init()		},		methods: {			init() {				this.reset()			},			// 开始倒计时			start() {				if (this.runing) return				// 标识为进行中				this.runing = true				// 结束时间戳 = 此刻时间戳 + 剩余的时间				this.endTime = Date.now() + this.remainTime				this.toTick()			},			// 根据是否展示毫秒,执行不同操作函数			toTick() {				if (this.millisecond) {					this.microTick()				} else {					this.macroTick()				}			},			macroTick() {				this.clearTimeout()				// 每隔一定时间,更新一遍定时器的值				// 同时此定时器的作用也能带来毫秒级的更新				this.timer = setTimeout(() => {					// 获取剩余时间					const remain = this.getRemainTime()					// 重设剩余时间					if (!isSameSecond(remain, this.remainTime) || remain === 0) {						this.setRemainTime(remain)					}					// 如果剩余时间不为0,则继续检查更新倒计时					if (this.remainTime !== 0) {						this.macroTick()					}				}, 30)			},			microTick() {				this.clearTimeout()				this.timer = setTimeout(() => {					this.setRemainTime(this.getRemainTime())					if (this.remainTime !== 0) {						this.microTick()					}				}, 50)			},			// 获取剩余的时间			getRemainTime() {				// 取最大值,防止出现小于0的剩余时间值				return Math.max(this.endTime - Date.now(), 0)			},			// 设置剩余的时间			setRemainTime(remain) {				this.remainTime = remain				// 根据剩余的毫秒时间,得出该有天,小时,分钟等的值,返回一个对象				const timeData = parseTimeData(remain)				this.$emit('change', timeData)				// 得出格式化后的时间				this.formattedTime = parseFormat(this.format, timeData)				// 如果时间已到,停止倒计时				if (remain <= 0) {					this.pause()					this.$emit('finish')				}			},			// 重置倒计时			reset() {				this.pause()				this.remainTime = this.time				this.setRemainTime(this.remainTime)				if (this.autoStart) {					this.start()				}			},			// 暂停倒计时			pause() {				this.runing = false;				this.clearTimeout()			},			// 清空定时器			clearTimeout() {				clearTimeout(this.timer)				this.timer = null			}		},		beforeDestroy() {			this.clearTimeout()		}	}</script><style	lang="scss"	scoped>	@import "../../libs/css/components.scss";	$u-count-down-text-color:$u-content-color !default;	$u-count-down-text-font-size:15px !default;	$u-count-down-text-line-height:22px !default;	.u-count-down {		&__text {			color: $u-count-down-text-color;			font-size: $u-count-down-text-font-size;			line-height: $u-count-down-text-line-height;		}	}</style>
 |