zoukankan      html  css  js  c++  java
  • React中需要多个倒计时的问题

    最近有一个需求是做一个闪购列表,列表中每一个商品都有倒计时,如果每一个倒计时都去生成一个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>
            );
        }
    }
    
  • 相关阅读:
    【POJ 3162】 Walking Race (树形DP-求树上最长路径问题,+单调队列)
    【POJ 2152】 Fire (树形DP)
    【POJ 1741】 Tree (树的点分治)
    【POJ 2486】 Apple Tree (树形DP)
    【HDU 3810】 Magina (01背包,优先队列优化,并查集)
    【SGU 390】Tickets (数位DP)
    【SPOJ 2319】 BIGSEQ
    【SPOJ 1182】 SORTBIT
    【HDU 5456】 Matches Puzzle Game (数位DP)
    【HDU 3652】 B-number (数位DP)
  • 原文地址:https://www.cnblogs.com/minz/p/9346726.html
Copyright © 2011-2022 走看看