iT邦幫忙

0

React-視窗滾動改變DOM

一開始我想實現一個辦法
就是在滑鼠滾動到指定位置時
我指定的區塊會浮現出來
滑鼠往上滾時,區塊會一起消失

於是此處是一開始的程式

const About=document.getElementsByClassName('about')[0];
const [scroll,setScroll]=useState(
  document.body.offsetTop>About.offsetTop?true:false
);

window.onscroll=()=>{			
  setScroll(
  document.body.offsetTop>About.offsetTop?true:false
);

const scrollFade={opacity:scroll?'1':'0',paddingTop:scroll?'100px':'300px'};

想當然爾
開始出現報錯

TypeError: Cannot read properties of undefined (reading 'offsetTop')

(因為我還是個react小白...這邊我還是不知道為什麼會報錯)

甚至是以為前面的document.body.offsetTop有問題
改為window.scrollY
(後來測試是兩種方法都可以用)

於是我把這段的邏輯改成false

const [scroll,setScroll]=useState(false);

讓網頁一開始讀取時
區塊是隱藏的
一開始的想法邏輯是
不管我在網頁何處重新讀取
都會先經過useState的三元判斷式先判斷
來達成區塊是否隱藏的目的
但改為false因為後面的狀態改變
一樣有達到同樣的目的

再來是第二段window.onscroll碰到的問題
在這邊我忘了這個方法重複使用的話
前面使用的方法會被覆蓋過去
於是後來使用addEventLisener
後來完整的寫法為

const [scroll,setScroll]=useState(false);

window.addEventListener('scroll',()=>{
  const About=document.getElementsByClassName('about')[0];
  setScroll(
  window.scrollY>About.getBoundingClientRect().top?true:false
  ); 
});

這邊為什麼會使用getBoundingClientRect()這個方法呢?
是因為發現offsetTop會比getBoundingClientRect().top
感應到的距離來的更遠
offsetTop必須在指定目標過了視窗才會感應
於是選擇使用getBoundingClientRect().top這個方法
更能貼近我所想要的效果


1 則留言

1
Todd
iT邦新手 3 級 ‧ 2021-11-29 10:46:28

首先,不建議在React裡操作DOM,以及去對DOM做事件綁定等等的操作。
但如果還是有必要取得DOM的資訊的話建議是使用ref
所以如果你要拿 About 這個Component我是建議用ref取binding後,
ref.current.offsetTop 去取得

我之前的做法是利用 IntersectionObserver 包裝成一個custom hook,
裡面利用ref去綁定我要切換顯示的element。

至於TypeError: Cannot read properties of undefined (reading 'offsetTop') 為什麼會出錯,我的推論是那時候DOM還沒渲染所以讀不到offsetTop 所以useState也無法正常的set initialState

小白 iT邦新手 5 級 ‧ 2021-12-01 00:14:22 檢舉

感謝您的建議!!
目前我也還在練習用ref來取得DOM的資訊

我要留言

立即登入留言