当前位置: 移动技术网 > IT编程>开发语言>JavaScript > 使用react render props实现倒计时的示例代码

使用react render props实现倒计时的示例代码

2019年06月01日  | 移动技术网IT编程  | 我要评论

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。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网