时、分、秒、倒计时组件
封装一个待付款商品时分秒倒计时组件
父组件 导入使用
<view class="countert"><view class="pay"><view class="item"><view class="top"><view class="img"><img src="" alt="" /></view><view class="title"><view class="label">商品名称商品名称商品名称商品名称</view><view class="price">应付 <text class="t1">T 349.99</text></view></view><view class="obligation"><text class="ob1">待付款</text><text class="ob2">T349.99</text></view></view><view class="bottom"><view class="time"><view class="label">剩余</view> //主要代码<countdown :end-time="endTime" @finish="onCountdownFinish"/></view><view class="btnare"><view class="btn1">取消订单</view><view class="btn2" @click="goPay">去付款</view></view></view> </view></view></view>
</template>
<script setup>import { ref, onMounted } from 'vue'import countdown from './countdown.vue'const endTime = ref(null)onMounted(async () => {// 模拟API调用// const res = await api.getEndTime()// endTime.value = res.data.endTime// 示例:设置一个未来的时间戳(当前时间+24小时)endTime.value = Math.floor(Date.now() / 1000) + 24 * 3600})const onCountdownFinish = () => {console.log('倒计时结束')// 可以在这里处理倒计时结束的逻辑// 比如刷新页面、提示用户等}const goPay = () => {uni.navigateTo({url: '/pages/pay/pay'})}
</script>
子组件(重要)直接复制粘贴使用
<!-- components/Countdown.vue -->
<template><view class="countdown"><text class="time-text">{{ formattedTime.hours }}</text><text class="separator">:</text><text class="time-text">{{ formattedTime.minutes }}</text><text class="separator">:</text><text class="time-text">{{ formattedTime.seconds }}</text></view></template><script setup>import { ref, computed, onMounted, onUnmounted, watch } from 'vue'// 定义propsconst props = defineProps({// 后端返回的时间戳(秒)endTime: {type: [Number, String],default: null},// 或者直接传入剩余秒数remainSeconds: {type: [Number, String],default: null}})// 定义事件const emit = defineEmits(['finish'])// 剩余秒数const remainingSeconds = ref(0)let timer = null// 计算格式化的时间const formattedTime = computed(() => {const totalSeconds = remainingSeconds.valueif (totalSeconds <= 0) {return {hours: '00',minutes: '00',seconds: '00'}}const hours = Math.floor(totalSeconds / 3600)const minutes = Math.floor((totalSeconds % 3600) / 60)const seconds = totalSeconds % 60return {hours: hours.toString().padStart(2, '0'),minutes: minutes.toString().padStart(2, '0'),seconds: seconds.toString().padStart(2, '0')}})// 初始化倒计时const initCountdown = () => {if (props.endTime) {// 基于结束时间戳计算const now = Math.floor(Date.now() / 1000)remainingSeconds.value = Math.max(0, props.endTime - now)} else if (props.remainSeconds !== null) {// 直接使用剩余秒数remainingSeconds.value = Math.max(0, parseInt(props.remainSeconds))}}// 开始倒计时const startCountdown = () => {// 清除之前的定时器if (timer) {clearInterval(timer)}initCountdown()// 如果剩余时间大于0,开始倒计时if (remainingSeconds.value > 0) {timer = setInterval(() => {remainingSeconds.value--if (remainingSeconds.value <= 0) {clearInterval(timer)timer = nullemit('finish')}}, 1000)}}// 重置倒计时const resetCountdown = () => {startCountdown()}// 监听props变化watch([() => props.endTime, () => props.remainSeconds], () => {startCountdown()})// 组件挂载时启动倒计时onMounted(() => {startCountdown()})// 组件销毁时清除定时器onUnmounted(() => {if (timer) {clearInterval(timer)}})// 暴露方法和属性defineExpose({resetCountdown,remainingSeconds})</script><style scoped>.countdown {display: flex;align-items: center;justify-content: center;}.time-text {font-family: PingFang SC, PingFang SC;font-weight: 400;font-size: 28rpx; color: #212429; padding: 0 2rpx;/* background-color: #f5f5f5;padding: 10rpx 15rpx;border-radius: 8rpx; */}.separator {font-size: 28rpx;font-weight: 500;color: #333333;margin: 0 10rpx;}</style>
效果图: