国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > JS > 正文

JavaScript觸發onScroll事件的函數節流詳解

2024-05-06 16:33:38
字體:
來源:轉載
供稿:網友

問題描述

常見的網站布局,頂部一個導航欄,我們假設本頁面共有四個欄目:分別為A、B、C、D,我們點擊A,錨點跳轉至A欄目,同時頂部的A按鈕高亮;點擊B,錨點跳轉至B欄目,同時頂部的B按鈕高亮;我們在Main組件里面滾動,滾動到B模塊時,B按鈕高亮。以上是我們經常會在開發中遇到的一個模型。如果是在以前,用jQuery作前端開發的話,實在是太熟悉不過了。

解決方案

主要想談談在React組件化開發中的性能優化方法。

我們的頁面結構是這樣的

<div className={style.main} id="main" ref={(main) => { this.main = main; }} onScroll={ ((/detail/.test(this.props.location.pathname))) ? (() => this.throttle()()) : null }> {this.props.children} <Footer />

我們在main組件里設定onScroll事件,在這個事件中,我們觸發action,通過redux將狀態的變化傳遞到子組件。

我的scroll事件觸發函數是這樣的(忽略一長串的if else,這是一個解決了一下午的bug的終極解決方案,此文不做累述)

 handleScroll() { const { changeScrollFlag } = this.props.actions; // 根據滾動距離修改TitleBox的樣式 const { basicinformation, holderinformation, mainpeople, changerecord } = { basicinformation: document.getElementById('basicinformation').offsetTop - 121, holderinformation: document.getElementById('holderinformation').offsetTop - 121, mainpeople: document.getElementById('mainpeople').offsetTop - 121, changerecord: document.getElementById('changerecord').offsetTop - 121, }; if (window.screen.availHeight > this.main.scrollTop) { document.getElementById('gototop').style.display = 'none'; } else { document.getElementById('gototop').style.display = 'block'; } // 得到基礎信息區域、股東信息區域、主要人員區域、變更記錄區域的offsetTop,我們把它用來跟main的scrollTop比較 // 比較的結果觸發action,改變TitleBox組件樣式 if (this.main.scrollTop < holderinformation) { // 基礎信息區域 if (basicinformation === -121) { // 如果基礎信息模塊不存在,我們什么也不做(當然理論上基礎信息模塊應該是會有的) return; } changeScrollFlag(1); return; } else if (this.main.scrollTop < mainpeople) { // 股東信息區域 changeScrollFlag(2); if (holderinformation === -121) { // 如果股東信息欄目不存在,在滾動的時候我們不應該強行把TileBox的高亮按鈕設置為holderinformation // 因為holdinformation并不存在,我們跳到前一個按鈕,讓基礎信息按鈕高亮 changeScrollFlag(1); return; } return; } else if (this.main.scrollTop < changerecord) { // 主要人員區域 changeScrollFlag(3); if (mainpeople === -121) { // 如果主要人員欄目不存在,在滾動的時候我們不應該強行把TileBox的高亮按鈕設置為mainpeople // mainpeople并不存在,我們跳到前一個按鈕,讓基礎信息按鈕高亮 changeScrollFlag(2); if (holderinformation === -121) { // 如果主要人員欄目不存在,而且連股東信息欄目也沒有,我們跳到高亮基礎信息欄目 changeScrollFlag(1); return; } return; } return; } else if (this.main.scrollTop > changerecord) { // 與上面同理 // 變更記錄區域 changeScrollFlag(4); if (changerecord === -121) { changeScrollFlag(3); if (mainpeople === -121) { changeScrollFlag(2); if (holderinformation === -121) {  changeScrollFlag(1);  return; } return; } return; } return; }}

其中,changeScrollFlag()函數是我們的action處理函數。

我們的函數節流

throttle() { // onScroll函數節流 let previous = 0; // previous初始設置上一次調用 onScroll 函數時間點為 0。 let timeout; const wait = 250; // 250毫秒觸發一次 return () => { const now = Date.now(); const remaining = wait - (now - previous); if (remaining <= 0) { if (timeout) { window.clearTimeout(timeout); } previous = now; timeout = null; this.handleScroll(); } else if (!timeout) { timeout = window.setTimeout(this.handleScroll, wait); } };}

我們的節流函數返回一個函數,設定一個時間戳,如果我們時間戳的差值較小,我們什么也不做,但我們的時間戳的差值較大,清除定時器,觸發scroll函數。這樣看起來似乎挺簡單,對,確實是挺簡單的。

那么在子組件我們還需要怎么做呢?

接收action

二級容器型組件接收action,通過二級容器型組件傳遞props至三級展示型組件。

我們一定要在componentWillReceiveProps接收到這個props。

記住,在componentWillReceiveProps里使用this.props是并不能夠接收到props的變化的!!!組件生命周期函數含有一個自己的參數。

 componentWillReceiveProps(nextProps) { // 在compoWillReceiveProps里接收到Main組件里所觸發onScroll事件的改變activebtn樣式的index // 并且設置為本組件的state this.setState({ activebtn: nextProps.scrollFlag.scrollIndex, });}

我們的state控制我們高亮的按鈕是第幾個,它是一個數字。

更改導航條的樣式

在這里,我使用了React周邊的庫:classnames,詳情參見其api。

<span className={classnames({ [style.informationactive]: (this.state.activebtn === 1), })} onClick={() => this.handleClick(1, 'basicinformation')}>

在此,我們完成了一次從頂層組件觸發事件,并做到函數節流,將事件一層層傳遞至底層展示型組件的一個過程。
最近一些關于前端開發的感慨

  1. 不要在組件中反復調用一個函數,這樣會造成巨大的消耗!我們可以通過三元運算符、模板字符串做到的事情,請勿寫一個新的函數。
  2. jsx不要太過于冗余。我們盡量寫成變量的形式,不然頁面結構復雜,不易于我們捕捉bug。
  3. 減少后端請求,能存cookie則存cookie,能存localStorge則存localStorge。
  4. 簡單的組件盡量自己寫,請勿使用別人的組件,否則在需求更改、樣式調整上會出現巨大困難并做一些無意義的事兒。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流。


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 长沙县| 抚顺县| 儋州市| 岑巩县| 岳普湖县| 新蔡县| 磴口县| 东莞市| 杭锦后旗| 佛冈县| 开封县| 吐鲁番市| 紫阳县| 玉溪市| 隆回县| 苍南县| 甘孜县| 江门市| 静海县| 凤山市| 无棣县| 陵川县| 中卫市| 永春县| 通化市| 嘉义县| 闸北区| 商丘市| 公安县| 宁化县| 延吉市| 新兴县| 阳朔县| 凤庆县| 芜湖市| 息烽县| 宣武区| 宜良县| 济宁市| 尼木县| 宁陵县|