React倒計時功能實現——解耦通用


React倒計時功能實現——解耦通用

需求分析

需求

在某個頁面中需要有一個倒計時的功能,倒計時 5 s,5s鍾后跳轉到新的界面

分析

  • 首先是實現倒計時功能
  • 其次是實現在每倒計時 1 s后頁面上要執行 倒計時秒數變化的功能
  • 最后是實現倒計時完成后 跳轉到指定頁面的功能

初版做法

代碼

let waitTime = 5
class DemoPage extends React.Component {
	constructor(props) {
		super(props);
		this.state = {
			time: '',
		};
	}
	componentDidMount = () => {
		this.countDown();
    };
	countDown = () => {
        if (waitTime > 0) {
            waitTime--;
           this.setState({
               time:waitTime
           })
        } else {
            history.push('/Login')
            return;
        }
        setTimeout(() => {
            this.countDown();
        }, 1000);
	}

	render() {
		todoInfo = this.state.time + '秒后跳轉至登錄界面';
		return (
			<div>
				todoInfo
			</div>
		);
	}
}
export default DemoPage;

問題分析

時間設置為全局變量,糟糕的做法,

  • 修改不方便
  • 難於閱讀和理解
  • 全局變量的值極不安全,可能被任何程序修改

改進版

代碼

class DemoPage extends React.Component {
	constructor(props) {
		super(props);
		this.state = {
			time: '',
		};
	}
	componentDidMount = () => {
		this.countDown(5);//倒計時時間可隨意調整,且可讀性強
    };
	countDown = (waitTime) => {
        if (waitTime > 0) {
            waitTime--;
           this.setState({
               time:waitTime
           })
        } else {
            history.push('/Login')
            return;
        }
        setTimeout(() => {
            this.countDown(waitTime);
        }, 1000);
	}

	render() {
		todoInfo = this.state.time + '秒后跳轉至登錄界面';
		return (
			<div>
				todoInfo
			</div>
		);
	}
}
export default DemoPage;

改進后將時間作為參數放到countDown里面,方便隨意設置倒計時時間

進一步分析問題:

上面的做法,

  • setState的操作只能寫在本組件,與本組件緊耦合在一起,無法實現多組件復用
  • history.push('/Login') 只能用在umi 框架中,與框架緊耦合在一起,無法實現普適應用

進一步改進

針對本問題的需求,可以將業務場景擴大為:

  • 倒計時功能
  • 倒計時過程中 需要做某事 doSomethingDuringCountDown()
  • 倒計時結束后 需要做某事 doSomethingAfterCountDown()

這樣的話,倒計時的功能就可以使用的更加的靈活了。

方案

將函數作為參數傳遞到countDown()方法中

doSomethingDuringCountDown()doSomethingAfterCountDown()作為參數傳遞到countDown方法中,

具體的方法實現,根據自己頁面的需求來實現。

代碼

//utils.js

export countDown = (waitTime,doSomethingDuringCountDown,doSomethingAfterCountDown){
      if (waitTime > 0) {
        waitTime--;
          if(doSomethingDuringCountDown){
               doSomethingDuringCountDown()
          }    
        } else {
            if(doSomethingAfterCountDown){
                doSomethingAfterCountDown()
            }  
            return;
        }
        setTimeout(() => {
            countDown(waitTime,doSomethingDuringCountDown,doSomethingAfterCountDown);
        }, 1000);
}

實例

//DemoPage.jsx
import { countDown } from 'utils.js'

class DemoPage extends React.Component {
	constructor(props) {
		super(props);
		this.state = {
			time: '',
		};
	}
	componentDidMount = () => {
		countDown(5,this.waitTimeStateChange,this.linkTo);
    }

    waitTimeStateChange = (time) => {
        this.setState({
            time: time,
        })
    }
    linkTo = () => {
        history.push(ToBeReviewedShowData.linkUrl)
    }	
	render() {
		todoInfo = this.state.time + '秒后跳轉至登錄界面'
		return (
			<div>
				todoInfo
			</div>
		)
	}
}
export default DemoPage


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM