小程序实现一个 倒计时组件

news/2024/7/20 2:03:46 标签: 小程序, vue.js

小程序实现一个 倒计时组件

需求背景

  • 要做一个倒计时,可能是天级别,也可能是日级别,时级别,而且每个有效订单都要用,就做成组件了

效果图

Sep-14-2023 16-16-49.gif

Sep-14-2023 16-54-44.gif

需求分析

  1. 需要一个未来的时间戳,或者在服务度直接下发一个未来到现在时间差,我们只需要做倒计时
  2. 进入页面,看是否已经结束, 如果没结束就调用倒计时函数
  3. 每隔1000,做时间戳(毫秒) -1000。边做tick ,边做时间格式化。
  4. 每次调用前,先清除上一个定时器
  5. 组件销毁的时候,也要清除一下定时器

代码实现

  1. 设置初始值,也是1秒,这里单位时毫秒
const interval = 1000;
  1. 进入页面,初始化完成。开始判断是否结束
lifetimes: {
		ready() {
			this.startCountdown();
		},
		detached() {
			clearTimeout(this.timer);
		},
	},

startCountdown() {
    const lastTime = this.initTime(this.properties.expireTime); // 这一步,如果服务端返回了未来到现在的差值,则不需要自己计算时间差了
    // 如果最终时间 < 1000ms 说明 已经过期了,就不用展示倒计时了.
    if (lastTime > interval) {
    // 格式化要展示的数据
    this.defaultFormat(lastTime);
    this.setData({
            isCountOver: true, // 标识可以显示倒计时
            lastTime, // set lastTime
    });
    // 调用倒计时函数,主要的逻辑就是每隔1000ms ,让lastTime - 1000
        this.tick();
        }
    },

初始化时间: 如果服务度返回了时间差,这一步不用处理

//初始化时间
initTime(expireTime) {
    let lastTime = Number(new Date(expireTime * 1000)) - new Date().getTime();
    console.log('lastTime', lastTime);
    return Math.max(lastTime, 0);
},

时间的格式化处理,这里都是固定代码,没什么含量

//默认处理时间格式
defaultFormat(time) {
    const days = 60 * 60 * 1000 * 24;
    const hours = 60 * 60 * 1000;
    const minutes = 60 * 1000;
    const d = Math.floor(time / days);
    const h = Math.floor((time % days) / hours);

    const m = Math.floor((time % hours) / minutes);
    const s = Math.floor((time % minutes) / 1000);

    this.setData({
            d: this.fixedZero(d),
            h: this.fixedZero(h),
            m: this.fixedZero(m),
            s: this.fixedZero(s),
    });
},
// 格式化时间加0
fixedZero(val) {
        return val < 10 ? `0${val}` : val;
},

tick 倒计时函数

tick() {
    let { lastTime } = this.data;
    this.timer = setTimeout(() => {
    // 每次定时器之前,先把上一个定时器清除
        clearTimeout(this.timer);
    // 如果倒计时结束,这是结束的状态
            if (lastTime < interval) {
                    this.setData({
                            lastTime: 0,
                            isCountOver: false,
                    });
            } else {
    // 如果倒计时正常,则每次 -1000 ,并且格式化时间。再次调用tick,直到倒计时结束
                    lastTime -= 1000;
                    this.setData(
                            {
                                    lastTime,
                            },
                            () => {
                                    this.defaultFormat(lastTime);
                                    this.tick();
                            },
                    );
            }
    }, interval);
    },

完整代码

  • 父组件(我这里传了一个比较大的时间戳,2024,10.1结束的时间戳)
<order-time expireTime="{{ 1727712000 }}">
    <view slot="desc">还剩</view>
</order-time>

  • 子组件 (wxml)
<view wx:if="{{ isCountOver }}" class="timer-wrap">
	<slot name="desc" />
	<view class="reset-time">
		<text wx:if="{{ d != '00' }}"> {{ d }}</text>
		{{ h }}:{{ m }}:{{ s }}</view
	>
</view>
<view wx:else class="reset-time"> {{ emptyType === '1' ? '已超时': '' }} </view>

  • 子组件 (js)
let interval = 1000;
Component({
	options: {
		multipleSlots: true,
	},
	properties: {
		expireTime: {
			type: String,
		},
		emptyType: {
			type: String,
			value: '1',
		},
	},

	lifetimes: {
		ready() {
			this.startCountdown();
		},
		detached() {
			clearTimeout(this.timer);
		},
	},

	/**
	 * 组件的初始数据
	 */
	data: {
		d: 0, //天
		h: 0, //时
		m: 0, //分
		s: 0, //秒
		lastTime: '', //倒计时的时间戳
		isCountOver: false, // 倒计时是否完成
	},

	/**
	 * 组件的方法列表
	 */
	methods: {
		startCountdown() {
			const lastTime = this.initTime(this.properties.expireTime);

			if (lastTime > interval) {
				this.defaultFormat(lastTime);
				this.setData({
					isCountOver: true,
					lastTime,
				});

				this.tick();
			}
		},
		//默认处理时间格式
		defaultFormat(time) {
			const days = 60 * 60 * 1000 * 24;
			const hours = 60 * 60 * 1000;
			const minutes = 60 * 1000;
			const d = Math.floor(time / days);
			const h = Math.floor((time % days) / hours);

			const m = Math.floor((time % hours) / minutes);
			const s = Math.floor((time % minutes) / 1000);

			this.setData({
				d: this.fixedZero(d),
				h: this.fixedZero(h),
				m: this.fixedZero(m),
				s: this.fixedZero(s),
			});
		},

		//定时事件
		tick() {
			let { lastTime } = this.data;
			this.timer = setTimeout(() => {
				clearTimeout(this.timer);
				if (lastTime < interval) {
					this.setData({
						lastTime: 0,
						isCountOver: false,
					});
				} else {
					lastTime -= 1000;
					this.setData(
						{
							lastTime,
						},
						() => {
							this.defaultFormat(lastTime);
							this.tick();
						},
					);
				}
			}, interval);
		},

		//初始化时间
		initTime(expireTime) {
			let lastTime = Number(new Date(expireTime * 1000)) - new Date().getTime();
			console.log('lastTime', lastTime);
			return Math.max(lastTime, 0);
		},

		// 格式化时间加0
		fixedZero(val) {
			return val < 10 ? `0${val}` : val;
		},
	},
});


  • 遇到相关变量,自己更改即可

End: 写作粗陋,有纰漏,建议之处,多多指教~~~


http://www.niftyadmin.cn/n/5026850.html

相关文章

图神经网络系列之序章

文章目录 一、为什么需要图神经网络&#xff1f;二、图的定义1.图的定义和种类2.一些关于图的重要概念2.1 子图2.2 连通图2.3 顶点的度、入度和出度2.4 边的权和网2.5 稠密图、稀疏图 3.图的存储结构3.1 邻接矩阵3.2 邻接表3.3 边集数组3.4 邻接多重表3.5 十字链表3.6 链式前向…

骨传导耳机有害处吗、骨传导耳机真的不好用吗?

骨传导耳机没有害处。 骨传导耳机是通过将声音传递到颅骨&#xff0c;再由颅骨传递到内耳&#xff0c;从而达到听声音的效果&#xff0c;与传统的耳机不同。 因此&#xff0c;骨传导耳机不会直接对人的身体健康、耳朵产生压力和损伤&#xff0c;也不会影响耳道和中耳的正常功能…

云原生Kubernetes:pod基础与配置

目录 一、理论 1.pod 2.pod容器分类 3.镜像拉取策略 4.pod 的重启策略 二、实验 1.Pod容器的分类 2.镜像拉取策略 三、问题 1.apiVersion 报错 2.pod v1版本资源未注册 3.格式错误 4.取行显示指定pod信息 四、总结 一、理论 1.pod (1) 概念 Pod是kubernetes中…

c语言练习题56:变种水仙花

变种水仙花 描述 变种水仙花数 - Lily Number&#xff1a;把任意的数字&#xff0c;从中间拆分成两个数字&#xff0c;比如1461 可以拆分成&#xff08;1和461&#xff09;,&#xff08;14和61&#xff09;,&#xff08;146和1),如果所有拆分后的乘积之和等于自身&#xff0c…

App测试中ios和Android有哪些区别呢?

App测试中&#xff0c;大家最常问到的问题就是&#xff1a;ios和 Android有什么区别呢&#xff1f; 在Android端&#xff0c;我们经常会使用 JavaScript、 HTML、 CSS等技术来编写一些简单的 UI界面。而 iOS端&#xff0c;我们经常会使用到 UI设计、界面布局、代码结构、 API等…

SpringCloud-Gateway网关实现入参统一解密

1.添加依赖 剩下的依赖自行添加... <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency> 2.创建配置文件 这里我使用了Nacos&#xff0c;使用时需要添加Nac…

WebGL透视投影

目录 透视投影 透视投影可视空间 可视空间构造效果图 Matrix4.setPerspective&#xff08;&#xff09; 三角形与可视化空间的相对位置 示例代码 代码详解 示例效果 投影矩阵的作用 透视投影矩阵对物体进行了两次变换 透视投影变换示意图 透视投影 在透视投影下&…

Java 包名中包含多个自然单词

Java包名可以包含多个自然单词&#xff0c;但是不建议包含太多自然单词&#xff0c;以避免命名过长难以阅读和编写。Java社区普遍推荐使用逆域名命名法&#xff08;Reverse Domain Name Notation&#xff0c;也称倒置域名命名法&#xff09;&#xff0c;即将公司或组织的域名倒…