最近有一个需求是做一个闪购列表,列表中每一个商品都有倒计时,如果每一个倒计时都去生成一个setTimeout的话,一个页面就会有很多定时器,感觉这种做法不是非常好,于是换了一个思路。

思路是这样的,一个页面只生成一个定时器。页面利用对象去维护一个回调函数列表,key可以是id等唯一标识,value就是更新时间的函数,我这里用的是setState。提供一个往对象里添加回调函数的方法和一个移除回调函数的方法。

// 用于存放每个倒计时的回调方法
const countDownFuncList = {}; const addFunc = (key, func) => {
countDownFuncList[key] = func;
}
const removeFunc = (key) => {
delete countDownFuncList[key];
}

生成一个定时器,隔一定的时间就去遍历回调函数列表,调用里面的函数。

let intervalHandler = -1;
const countDown = () => {
if (intervalHandler !== -1) {
clearTimeout(intervalHandler);
}
intervalHandler = setTimeout(() => {
const now = new Date();
Object.keys(countDownFuncList).forEach((key) => {
const item = countDownFuncList[key];
if (typeof item === 'function') {
item(now);
}
})
}, 300);
}  

具体调用是调用timeContent方法来处理展示的时间。

const timeContent = (millisecond) => {
const second = millisecond / 1000;
let d = Math.floor(second / 86400);
let h = Math.floor((second % 86400) / 3600);
let m = Math.floor(((second % 86400) % 3600) / 60);
let s = Math.floor(((second % 86400) % 3600) % 60); let countDownDOM;
if (d > 0) {
countDownDOM = (<div class="count-down">{d} 天 {h} : {m} : {s}</div>);
} else {
countDownDOM = (<div class="count-down">{h} : {m} : {s}</div>);
} return countDownDOM;
}

这个方法有一个缺点就是当前时间的获取,除了初始化步骤以外,之后的更新都是通过new Date()来获取的,这样存在获取的时间可能并不是正确的当前时间的问题。

完整代码如下:

// 用于存放每个倒计时的回调方法
const countDownFuncList = {}; const addFunc = (key, func) => {
countDownFuncList[key] = func;
}
const removeFunc = (key) => {
delete countDownFuncList[key];
} const timeContent = (millisecond) => {
const second = millisecond / 1000;
let d = Math.floor(second / 86400);
let h = Math.floor((second % 86400) / 3600);
let m = Math.floor(((second % 86400) % 3600) / 60);
let s = Math.floor(((second % 86400) % 3600) % 60); let countDownDOM;
if (d > 0) {
countDownDOM = (<div class="count-down">{d} 天 {h} : {m} : {s}</div>);
} else {
countDownDOM = (<div class="count-down">{h} : {m} : {s}</div>);
} return countDownDOM;
} let intervalHandler = -1;
const countDown = () => {
if (intervalHandler !== -1) {
clearTimeout(intervalHandler);
}
intervalHandler = setTimeout(() => {
const now = new Date();
Object.keys(countDownFuncList).forEach((key) => {
const item = countDownFuncList[key];
if (typeof item === 'function') {
item(now);
}
})
}, 300);
} countDown(); class CountDownItem extends React.Component {
constructor(props) {
super(props);
this.state = {
currentTime: this.props.nowDate
} this.parseDisplayTime = this.parseDisplayTime.bind(this);
} componentDidMount() {
const { id } = this.props;
// 往事件列表添加回调函数
addFunc(id, this.updateTime);
} componentWillUnmount() {
const { id } = this.props;
// 从事件列表移除回调函数
removeFunc(id);
} updateTime(time) {
this.setState({
currentTime: time
})
} parseDisplayTime() {
const { endTime, id } = this.props;
const { currentTime } = this.state;
const subtractTime = endTime - currentTime;
let countDownDOM = '';
if(subtractTime > 1000){
countDownTimeDOM = (
<div className="count-down-content">
{timeContent(subtractTime)}
</div>
);
}else{
removeFunc(id);
} return countDownDOM;
} render(){
return(
<div className="count-down-wrap">{this.parseDisplayTime()}</div>
);
}
}

React中需要多个倒计时的问题的更多相关文章

  1. react中简单倒计时跳转

    其实在react中实现倒计时的跳转方法有很多中,其中我认为较为好用的就是通过定时器更改state中的时间值. 首先在constructor中设置10秒的时间值: constructor () { su ...

  2. 理解React中es6方法创建组件的this

    首发于:https://mingjiezhang.github.io/(转载请说明此出处). 在JavaScript中,this对象是运行时基于函数的执行环境(也就是上下文)绑定的. 从react中的 ...

  3. 【原】React中,map出来的元素添加事件无法使用

    在使用react中,经常用到react的map函数,用法和jquery里中的map一样,但是,如果你在每个map出来的元素中添加,你会发觉添加的事件无法关联, 比如,我们很多的评论,我需要在每个评论下 ...

  4. React中props.children和React.Children的区别

    在React中,当涉及组件嵌套,在父组件中使用props.children把所有子组件显示出来.如下: function ParentComponent(props){ return ( <di ...

  5. Immutable 详解及 React 中实践

    本文转自:https://github.com/camsong/blog/issues/3 Shared mutable state is the root of all evil(共享的可变状态是万 ...

  6. React中父组件与子组件之间的数据传递和标准化的思考

    React中父组件与子组件之间的数据传递的的实现大家都可以轻易做到,但对比很多人的实现方法,总是会有或多或少的差异.在一个团队中,这种实现的差异体现了每个人各自的理解的不同,但是反过来思考,一个团队用 ...

  7. React中使用CSSTransitionGroup插件实现轮播图

    动画效果,是一个页面上必不可少的功能,学习一个新的东西,当然就要学习,如何用新的东西,用它的方法去实现以前的东西啦.今天呢,我就在这里介绍一个试用react-addons-css-transition ...

  8. 在React中使用Redux

    这是Webpack+React系列配置过程记录的第六篇.其他内容请参考: 第一篇:使用webpack.babel.react.antdesign配置单页面应用开发环境 第二篇:使用react-rout ...

  9. React中的路由系统

    React中的路由系统 提起路由,首先想到的就是 ASPNET MVC 里面的路由系统--通过事先定义一组路由规则,程序运行时就能自动根据我们输入的URL来返回相对应的页面.前端中的路由与之类似,前端 ...

随机推荐

  1. npm安装gulp-sass失败处理办法

    最近在做一个基于gulp的前端自动化的项目,在github上拉取代码后,按照正常的流程,首先我们要 npm  install ,在安装的过程中,一直提示我gulp-sass 安装失败,我用尽了好多办法 ...

  2. Mysql只Union用法

    MYSQL中的UNION UNION在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果. 举例说明: select * from table1 u ...

  3. Python3.4 获取百度网页源码并保存在本地文件中

    最近学习python 版本 3.4 抓取网页源码并且保存在本地文件中 import urllib.request url='http://www.baidu.com' #上面的url一定要写明确,如果 ...

  4. Thrift笔记(四)--Thrift client源码分析

    thrift文件 namespace java com.gxf.demo namespace py tutorial typedef i32 int // We can use typedef to ...

  5. 封装微信jssdk自定义分享代码

    var protocol = window.location.protocol; //获取协议 var host = window.location.host; //获取域名 var posuDoma ...

  6. Java入门到精通——框架篇之Hadoop概述

    一.Hadoop来历 Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明了倒排索引算法,通过加入了Map ...

  7. Java入门到精通——调错篇之Eclipse Java compiler level dose not match the version of the installed Java project

    一.错误现象. java项目显示红色,并且类中引用包中会报红色错误,在Eclipse下面显示下面错误提示如图: 二.错误原因. 通过字面意思一看就很明白java的版本不对. 三.解决办法. 3.1右键 ...

  8. IOS GCDAsyncSocket

    // // ViewController.m // 05.聊天室 // // Created by apple on 14/12/5. // Copyright (c) 2014年 heima. Al ...

  9. 从数据流角度管窥 Moya 的实现(一):构建请求

    相信大家都封装过网络层. 虽然系统提供的网络库以及一些著名的第三方网络库(AFNetworking, Alamofire)已经能满足各种 HTTP/HTTPS的网络请求,但直接在代码里用起来,终归是比 ...

  10. 2018.11.1 Hibernate中的Mapper关系映射文件

    Customer.hbm.xml 基本的参数都在里面了 <?xml version="1.0" encoding="UTF-8"?> <!DO ...