最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

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

来源:动视网 责编:小采 时间:2020-11-27 22:02:57
文档

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

使用react render props实现倒计时的示例代码:react的组件模式可以观看Michael Chan的演讲视频,平时大家常听到的react模式也是HOC, HOC的使用场景很多,譬如react-redux的connect,这里不赘述HOC相关,感兴趣可以自行了解。 首先是这样一个场景,我的业务需要实现倒计时,倒计时你懂得,倒计时经常应用在
推荐度:
导读使用react render props实现倒计时的示例代码:react的组件模式可以观看Michael Chan的演讲视频,平时大家常听到的react模式也是HOC, HOC的使用场景很多,譬如react-redux的connect,这里不赘述HOC相关,感兴趣可以自行了解。 首先是这样一个场景,我的业务需要实现倒计时,倒计时你懂得,倒计时经常应用在


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。

    文档

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

    使用react render props实现倒计时的示例代码:react的组件模式可以观看Michael Chan的演讲视频,平时大家常听到的react模式也是HOC, HOC的使用场景很多,譬如react-redux的connect,这里不赘述HOC相关,感兴趣可以自行了解。 首先是这样一个场景,我的业务需要实现倒计时,倒计时你懂得,倒计时经常应用在
    推荐度:
    标签: 实现 倒计时 React
    • 热门焦点

    最新推荐

    猜你喜欢

    热门推荐

    专题
    Top