最近有一个需求是做一个闪购列表,列表中每一个商品都有倒计时,如果每一个倒计时都去生成一个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. 二、MVC3+EF单表增删改查

    document 表为例 写入静态类 NorthwindDataProvider: Controller可直接调用:如 //获取document表全部数据 NorthwindDataProvider. ...

  2. java常用API之基本类型包装类

    基本类型包装类概述: 在实际程序使用中,程序界面上用户输入的数据都是以字符串类型进行存储的. 而程序开发中,我们需要把字符串数据,根据需求转换成指定的基本数据类型. 想实现字符串与基本数据之间转换,需 ...

  3. ajax异步请求/同源策略/跨域传值

    基本概念 Ajax 全称是异步的 JavaScript 和 XML . 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着可以在不重新加载整个网页的情况下,对网页的某部分进 ...

  4. Lucene 初识

    因为业务需要,虽然自己不是专门写搜索的,但是需要自己拼一些搜索条件去调用搜索的接口,而之前看的JVM crash里也涉及到了Lucene,所以大概了解一下. 参考文档: http://www.itey ...

  5. ASP.NET MVC 音乐商店 - 5 通过支架创建编辑表单 续

    查看 StoreManager 控制器的代码 现在,Store Manager 控制器中已经包含了一定数量的代码,我们从头到尾重新过一下. 首先,在控制器中包含了标准的 MVC 控制器的代码,为了使用 ...

  6. SQL Server2008宝典 全书代码

    -- ============================================= -- Create database template -- ==================== ...

  7. 【转】JavaScript 中值得注意的 for 循环

    在ECMAScript5(简称 ES5)中,有三种 for 循环,分别是: 简单for循环 for-in forEach 在2015年6月份发布的ECMAScript6(简称 ES6)中,新增了一种循 ...

  8. 使用embeded tomcat进行嵌入式javaee开发-启动tomcat

    昨天在网上研究了下关于将tomcat嵌入到主程序中进行运行,而不是像以前将一个web项目copy到tomcat中进行运行.之所以这样做的原因,即是因为项目部署到客户方,在进行更新的时候,需要手动地进行 ...

  9. ORACLE_SPOOL

    Question:When you use developer tool in oracle.However,you press Ctrl and click left-mouse in a tabl ...

  10. Sticky footers 套路

    [CSS Secrets] http://shop.oreilly.com/product/0636920031123.do 以饿了么商家信息的弹出层为例,布局如下: <!-- 饿了么 弹出层部 ...