使用 MutationObserver 監視DOM的背景更新,經驗筆記

前情提要

這次在專案上使用了sveltekit 作為前端框架,UI則是用bootstrap, 在列表頁的時候需要每5秒更新(圖1),取得最新的生理資訊。

列表頁(圖1)


但每5秒去得取api,其實是很耗資源的。尤其是長時間停留在頁面。(圖2)

Network背景資源(圖2)


主想法

為了減少資源耗損,當按下「檢視」打開彈窗(modal)的時候,背景更新可以先暫時,畢竟彈窗(modal)會佔據整個版面,focus都會在彈窗上,等彈窗(modal)關閉後 再繼續執行背景更新。(圖3)

彈窗開啟(圖3)


實際作法

如果要觀測彈窗(modal),就會需要動態監測dom的變化(圖4) , 需要觀察 modal-open,是否有開啟。

動態監測dom(圖4)

   在做法上使用了MutationObserver 來監視dom的變化,當監測到 body 的class 出現了.modal-open,代表彈窗已開啟,就可停止背景更新。(圖5)

MutationObserver監視.modal-open(圖5)

遇到的坑

照著MutationObserver監視.modal-open 來做背景更新的開關控管是成功了,但卻也延伸了其他問題——「切換到其他頁背景更新並不會停止」。 
切換到了B頁→A頁,B的背景更新並不會停止;從A頁C頁 ,A頁的背景更新並不會停止(圖6) ,也就表示 背景更新不會隨著切換頁面而停止。主要是因為在同一個SPA的特性,頁面不重載,DOM並沒有銷毀。

SPA的特性,頁面不重載(圖6)

填坑--解決方法

加入了writeable 動態的背景更新「開關管理」,更新writeable的狀態,搭配動態的讀取資料狀態的變化,類似redux的狀態管理。因為用的modal在每頁都是相同的,並不會因為切換頁面造成dom重新渲染,所以監測也並不會因為切換頁而消失。
設立了一個$modalObserver='',當彈窗(modal)開啟才給值 $modalObserver=0,關閉$modalObserver=1
$modalObserver 就可讀取到到最新的modal狀態,進而去執行該頁的背景更新,也就能避免累加的背景更新。(圖7)
當在A頁開啟modal的時候,就執行A頁的背景更新;當在B頁開啟modal的時候,就執行B頁的背景更新......依此類推。

加入writeable,共管各頁的modal狀態(圖7)


心得

這次的專案背景更新並不會因為切換頁就停止,SPA的特性也真是讓我學到很多。
以往傳統的方法,寫個location.href='指定頁',整個js 和dom 就會重新執行。
但使用了svelte後,只要這個dom還在,當物件有重複呼叫modal後,上次的資料是還會留存的。

使用writeable真的需要特別留意,之前在做換頁的時候把page綁在writeable上,只要writeable的page換頁有變動api就去執行,但也造成點選換頁越多api就執行越多次,摸了老半天一直找不到原因😅,最後只好打掉重練。

這次的經驗,writeable 更適合用在動態的狀態管理,透過最新的狀態在進而去做下一步。



留言