使用react render props实现倒计时的示例代码
程序员文章站
2022-06-22 15:39:52
react的组件模式可以观看michael chan的演讲视频,平时大家常听到的react模式也是hoc, hoc的使用场景很多,譬如react-redux的connect...
react的组件模式可以观看michael chan的演讲视频,平时大家常听到的react模式也是hoc, hoc的使用场景很多,譬如react-redux的connect,这里不赘述hoc相关,感兴趣可以自行了解。
首先是这样一个场景,我的业务需要实现倒计时,倒计时你懂得,倒计时经常应用在预告一个活动的开始,像秒杀,像开售抢购等,或者活动的截止。
我们来梳理一下这个倒计时的功能:
- 定时更新时间,以秒为度;
- 可以更新倒计时的截止时间,比如从10月1日更新为10月2日;
- 倒计时结束,执行对应结束逻辑;
- 倒计时结束,开启另一个活动倒计时;
- 同时有多个倒计时;
这个时候我便开始编码,考虑代码复用,我用class的模式实现一个倒计时:
class timer { constructor(time, countcb, timeoutcb) { this.countcb = countcb; this.timeoutcb = timeoutcb; this.setdelaytime(time); } intervalid = null; clearinterval = () => { if (this.intervalid) { clearinterval(this.intervalid); } } // 更新倒计时的截止时间 setdelaytime = (time) => { this.clearinterval(); if (time) { this.delaytime = time; this.intervalid = setinterval(() => { this.docount(); }, 1000); } } docount = () => { const timediffsecond = `${this.delaytime - date.now()}`.replace(/\d{3}$/, '000') / 1000; if (timediffsecond <= 0) { this.clearinterval(); if (typeof this.timeoutcb === 'function') { this.timeoutcb(); } return; } const day = math.floor(timediffsecond / 86400); const hour = math.floor((timediffsecond % 86400) / 3600); const minute = math.floor((timediffsecond % 3600) / 60); const second = math.floor((timediffsecond % 3600) % 60); // 执行回调,由调用方决定显示格式 if (typeof this.countcb === 'function') { this.countcb({ day, hour, minute, second, }); } } } export default timer;
通过class的方式可以实现我的上述功能,将格式显示交给调用方决定,timer只实现倒计时功能,这并没有什么问题,我们看调用方如何使用:
// 这是一个react组件部分代码 componentdidmount() { // 开启倒计时 this.countdownlivedelay(); } componentdidupdate() { // 开启倒计时 this.countdownlivedelay(); } componentwillunmount() { if (this.timer) { this.timer.clearinterval(); } } timer = null; countdownlivedelay = () => { const { countdowntime, ontimeout, } = this.props; if (this.timer) { return; } const time = countdowntime * 1000; if (time <= date.now()) { ontimeout(); } // new 一个timer对象 this.timer = new timer(time, ({ hour, minute, second }) => { this.setstate({ timedelaytext: `${formatetimestr(hour)}:${formatetimestr(minute)}:${formatetimestr(second)}`, }); }, () => { this.timer = null; if (typeof ontimeout === 'function') { ontimeout(); } }); } render() { return ( <span style={styles.text}>{this.state.timedelaytext}</span> ); }
查看这种方式的调用的缺点:调用方都需要手动开启倒计时,countdownlivedelay方法调用
总感觉不够优雅,直到我看到了react的render props, 突然灵关一现,来了下面这段代码:
let delaytime; // 倒计时组件 class timecountdown extends component { state = { day: 0, hour: 0, minute: 0, second: 0, } componentdidmount() { delaytime = this.props.time; this.startcountdown(); } componentdidupdate() { if (this.props.time !== delaytime) { delaytime = this.props.time; this.cleartimer(); this.startcountdown(); } } timer = null; cleartimer() { if (this.timer) { clearinterval(this.timer); this.timer = null; } } // 开启计时 startcountdown() { if (delaytime && !this.timer) { this.timer = setinterval(() => { this.docount(); }, 1000); } } docount() { const { ontimeout, } = this.props; // 使用math.floor((delaytime - date.now()) / 1000)的话会导致这里值为0,前面delaytime - date.now() > 0 const timediffsecond = (delaytime - `${date.now()}`.replace(/\d{3}$/, '000')) / 1000; if (timediffsecond <= 0) { this.cleartimer(); if (typeof ontimeout === 'function') { ontimeout(); } return; } const day = math.floor(timediffsecond / 86400); const hour = math.floor((timediffsecond % 86400) / 3600); const minute = math.floor((timediffsecond % 3600) / 60); const second = math.floor((timediffsecond % 3600) % 60); this.setstate({ day, hour, minute, second, }); } render() { const { render, } = this.props; return render({ ...this.state, }); } } export default timecountdown;
具体timecountdown代码可戳这里
调用方:
import timecountdown from 'timecountdown'; function formatetimestr(num) { return num < 10 ? `0${num}` : num; } // 业务调用倒计时组件 class calltimer extends component { ontimeout = () => { this.forceupdate(); } render() { // 传递render函数 return ( <span style={styles.statustext}> 距直播还有 <timecountdown time={time} ontimeout={() => { this.ontimeout(); }} render={({ hour, minute, second }) => { return ( <span> {formatetimestr(hour)}:{formatetimestr(minute)}:{formatetimestr(second)} </span> ); }} /> </span> ) } }
对比这种方式,通过传递一个函数render方法给到timecountdown组件,timecountdown组件渲染时执行props的render方法,并传递timecountdown的state进行渲染,这就是render props的模式了,这种方式灵活、优雅很多,很多场景都可以使用这种方式,而无需使用hoc。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: JS实现轮播图小案例
下一篇: JS实现元素的拖动与占位功能