91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

使用react render props實現倒計時的示例代碼

發布時間:2020-10-06 00:02:11 來源:腳本之家 閱讀:170 作者:EnjoyChan 欄目:web開發

react的組件模式可以觀看Michael Chan的演講視頻,平時大家常聽到的react模式也是HOC, HOC的使用場景很多,譬如react-redux的connect,這里不贅述HOC相關,感興趣可以自行了解。

首先是這樣一個場景,我的業務需要實現倒計時,倒計時你懂得,倒計時經常應用在預告一個活動的開始,像秒殺,像開售搶購等,或者活動的截止。

使用react render props實現倒計時的示例代碼

我們來梳理一下這個倒計時的功能:

  • 定時更新時間,以秒為度;
  • 可以更新倒計時的截止時間,比如從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。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

新巴尔虎左旗| 桂平市| 霍林郭勒市| 磴口县| 莱州市| 屯昌县| 连江县| 新平| 肥城市| 临城县| 夏河县| 武陟县| 兴安县| 大宁县| 鄂尔多斯市| 襄樊市| 苍山县| 六枝特区| 南木林县| 夏津县| 长乐市| 岚皋县| 台南市| 河曲县| 宁武县| 玉龙| 长白| 辽源市| 土默特右旗| 铜山县| 峨山| 江门市| 长沙市| 南安市| 泉州市| 大安市| 富锦市| 江源县| 南丰县| 延津县| 红桥区|