在vue2.0项目中一个简单的倒计时功能

本文介绍了一款用于平板支撑比赛的在线计时器的设计与实现。该计时器使用HTML、CSS和JavaScript构建,支持倒计时和实时计时功能,适用于运动赛事现场展示。

公司3月底有一个运动会项目,项目中有一项是平板支撑,参加比赛的人会通过扫二维的方式进入到报名页面,我们的页面会投到比赛现场的大屏幕上,当主持人说预备~,我则在页面上点击开始按钮,然后大屏幕上就会出现倒计时3~ 2~ 1~,之后主持人说开始,大屏幕上就开始计时。当最后一个坚持的人倒下了,就是全场坚持最久的人的秒数。http://www.jianshu.com/p/ee7ff3d1d93d

// 以下是html 代码 ------------ 
<template>
    <div class="container">
        // 显示倒计时数字的标签
        <div class="share-dialog" v-show="isShareCount">
            <div id="showtimes"></div>
        </div>
        // 开始按钮
        <a class="btn" href="javascript:void (0);" v-on:click="showTime(3)" v-show="isShowBtn">开始</a>
        // 停止按钮
        <a class="btn stop" href="javascript:void (0);" v-on:click="stopTimer">停</a>
        // 计时时间
        <div class="timer" v-show="isShowTimer"><strong>{{ timer }}</strong><span class="second">秒</span><span
            class="line"></span></div>
    </div>
</template>
// 以下是 css 代码 ------------
 <style lang="scss" rel="stylesheet/scss" scoped>
  .share-dialog {
        position: fixed;
        left: 0;
        top: 0;
        bottom: 0;
        right: 0;
        width: 100%;
        height: 100%;
        overflow: hidden;
        background: rgba(0, 0, 0, .5);
        z-index: 999;
        #showtimes {
            position: absolute;
            left: 50%;
            top: 50%;
            width: 500/75+rem;
            height: 500/75+rem;
            margin-left: -250/75+rem;
            margin-top: -250/75+rem;
            line-height: 500/75+rem;
            text-align: center;
            color: #fff;
            font-weight: bold;
            font-size: 460/75+rem;
            z-index: 1000;
        }
    }

    .timer {
        position: relative;
        margin: 30/75+rem auto 30/75+rem;
        width: 25%;
        height: 160/75+rem;
        line-height: 150/75+rem;
        text-align: center;
        background: #151414;
        border-radius: 20/75+rem;
    }

    strong {
        font-size: 120/75+rem;
        color: #fff;
        letter-spacing: 6px;
    }

    .line {
        position: absolute;
        top: 80/75+rem;
        left: 0;
        display: block;
        width: 100%;
        height: 2px;
        content: '';
        background: #fff;
        border-bottom: 1px solid #000;
    }

    .second {
        display: block;
        position: absolute;
        right: 15/75+rem;
        bottom: -40/75+rem;
        color: #fff;
        font-size: 24/75+rem;
    }

    .btn {
        margin: 30/75+rem auto 30/75+rem;
        display: block;
        width: 15%;
        height: 160/75+rem;
        line-height: 150/75+rem;
        text-align: center;
        font-size: 100/75+rem;
        color: #fff;
        font-weight: bolder;
        background: #e72b0e;
        border-radius: 20/75+rem;
        box-shadow: 0 10px 0 1px #ffad5a;
    }
</style>
// 以下是js代码 ------------
 export default{
        data(){
            return {
                timer: 0,
                si: '',
                isShareCount: false,
                isShowTimer: false,
                isShowBtn: true,
            }
        },
        methods: {
            // 比赛开始,计时开始
            startTimer(){
                let self = this;
                this.si = setInterval(function () {
                    self.timer++;
                }, 1000);
            },
            // 比赛结束,停止计时
            stopTimer(){
                let self = this;
                clearInterval(self.si);
            },
            //显示倒数秒数
            showTime(countdown){
                let self = this;
                self.isShareCount = true;
                self.isShowBtn = false;
                self.isShowFalseBtn = true;
                document.getElementById('showtimes').innerHTML = countdown;
                if (countdown == 0) {
                    self.isShareCount = false;
                    self.isShowTimer = true;
                    self.isShowFalseBtn = false;
                    document.getElementById('showtimes').innerHTML = "";
                    // 计时器开始计时
                    self.startTimer();
                } else {
                    countdown -= 1;
                    setTimeout(function () {
                        self.showTime(countdown);
                    }, 1000);
                }
            }
        }
    }
<think>好的,我现在需要帮用户解决在Vue 2.0中创建一个显示年月日的倒计时组件的问题。首先,我得理清楚用户的需求。用户想要计算从开始时间到结束时间的时间差,并以年月日的形式显示出来。那具体应该如何实现呢? 首先,我应该回顾一下Vue 2.0的基本知识,尤其是关于组件的创建和数据绑定。Vue的响应式系统是关键,因为倒计时需要实时更新显示的时间差。用户提到参考了引用[1]和[3],其中提到使用Date对象获取时间戳,并通过计算剩余时间。所以,我需要考虑如何在Vue中设置一个定时器,定期更新时间差。 接下来,我需要确定如何计算两个日期之间的时间差,并转换为年月日。这里可能会遇到一些问题,比如不同月份的天数不同,闰年的处理等。例如,计算年份差的时候,不能简单地将总毫秒数除以一年的固定毫秒数,而是需要逐年递减,直到剩余时间不足一年为止。同样,月份的处理也需要考虑每个月的天数不同,比如二月有28或29天。 然后,组件的结构方面,用户需要一个显示年月日的地方,可能使用计算属性来格式化时间差。同时,需要在组件销毁时清除定时器,避免内存泄漏。引用[2]中的getTimeStamp函数可能有用,但需要调整,因为用户需要的是年月日,而不仅仅是时间戳。 另外,用户可能希望开始时间和结束时间可以是动态的,比如通过props传入,这样组件可以复用。需要确保当开始时间或结束时间变化时,倒计时能重新计算。这里可能需要使用watch来监听props的变化,并重新初始化倒计时。 测试时需要考虑的情况包括结束时间早于开始时间的情况,这时候应该显示已结束。还有跨年、跨月的情况,比如从2023-02-28到2024-03-01,这样的时间差是否正确计算。 最后,如何将计算出的时间差显示在页面上,可能需要使用模板中的插值表达式,或者通过过滤器、方法返回格式化后的字符串。确保时间的更新是实时的,比如每秒更新一次,但为了性能,可能不需要太高的频率,因为年月日的变化较慢。 总结步骤:创建组件,接收开始和结束时间,计算时间差,转换为年月日,定时更新,处理组件销毁,处理边界情况。同时参考用户提供的引用,整合时间戳的计算方法,并利用Vue的响应式特性自动更新页面显示。</think>在Vue 2.0中创建显示年月日的倒计时组件可通过以下步骤实现: ### 一、创建倒计时组件 ```vue <template> <div> <p v-if="!expired">剩余时间:{{ years }}年 {{ months }}月 {{ days }}日</p> <p v-else>已结束</p> </div> </template> <script> export default { props: { startDate: { type: [String, Date], required: true }, // 格式:"YYYY-MM-DD HH:mm:ss" endDate: { type: [String, Date], required: true } }, data() { return { now: new Date().getTime(), intervalId: null }; }, computed: { startTime() { return new Date(this.startDate).getTime(); }, endTime() { return new Date(this.endDate).getTime(); }, totalDiff() { return Math.max(this.endTime - this.now, 0); }, expired() { return this.totalDiff === 0; }, // 时间差计算逻辑 years() { /* 具体实现见下文 */ }, months() { /* 具体实现见下文 */ }, days() { /* 具体实现见下文 */ } }, mounted() { this.intervalId = setInterval(() => { this.now = new Date().getTime(); }, 1000); }, beforeDestroy() { clearInterval(this.intervalId); } }; </script> ``` ### 二、实现年月日计算逻辑 ```javascript // 在computed中补充计算方法 years() { let remaining = this.totalDiff; const yearMs = 365 * 24 * 60 * 60 * 1000; let count = 0; while (remaining >= yearMs) { const testDate = new Date(this.startTime + (count + 1) * yearMs); // 处理闰年误差 if (testDate.getFullYear() > new Date(this.startTime + count * yearMs).getFullYear()) { remaining -= yearMs; count++; } else { break; } } return count; }, months() { let remaining = this.totalDiff - this.years * 365 * 24 * 60 * 60 * 1000; const monthMs = 30 * 24 * 60 * 60 * 1000; // 近似值 let count = 0; while (remaining >= monthMs) { const testDate = new Date(this.startTime + this.years * 365 * 24 * 60 * 60 * 1000 + (count + 1) * monthMs); // 处理月份天数差异 if (testDate.getMonth() === new Date(this.startTime + this.years * 365 * 24 * 60 * 60 * 1000 + count * monthMs).getMonth() + 1) { remaining -= monthMs; count++; } else { break; } } return count; }, days() { const remaining = this.totalDiff - this.years * 365 * 24 * 60 * 60 * 1000 - this.months * 30 * 24 * 60 * 60 * 1000; return Math.floor(remaining / (24 * 60 * 60 * 1000)); } ``` ### 三、使用示例 ```vue <template> <countdown start-date="2024-01-01 00:00:00" end-date="2025-05-15 23:59:59" /> </template> ``` ### 四、关键实现说明 1. **时间精度处理**:使用$1$秒间隔更新基准时间(`setInterval`),确保显示准确性[^3] 2. **闰年补偿**:年份计算通过实际日期测试避免闰年误差 3. **月份动态计算**:通过比较月份变化判断是否完整月 4. **性能优化**:使用`computed`属性自动缓存计算结果,避免重复计算
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值