監測元素resize

發表於2019-06-25

前言

近來有需求要做分頁,聽起來可能有點Low。 所以我要把Low的事情做得有點逼格。
分頁本身沒啥,但是資料量起來了,比如十萬。 要是不做點處理, 那你的頁面估計爽得很,機器也爽得很。 放心,我不會讓你這麼爽。

大量資料展現方案

比較流行的當然是虛擬滾動(無限滾動)。

  1. 始終展示的是有限的固定節點。
  2. 外層建立滾動層。

一句話,就是反覆利用固定節點展現資料。

其中還有兩個點

何時需要載入新的分頁資料

  1. scrollTop , clientHeight, scrollHeight
  2. IntersectionObserver (chrome 55+)

如何知道容器寬高變化
本文就圍繞著這個展開

因為使用的是react框架,使用了 react-window, react-window就是用來展現海量資料的react列表元件。
因為專案需要,還要不通尺寸一行展現不同數量的資料。 肯定有人就說,監聽window.resize。



沒錯,監聽resize一定程度,但是window.resize, 並不能讓我知道容器本身的尺寸,當
然可以通過getComputedStyle獲取。 要是window沒有resize的情況呢。


我就想實時的知道尺寸的變化。

尺寸變化監測方案

監測元素resize這裡有幾種方案的測試和原始碼。

Cross-Browser, Event-based, Element Resize Detection

思路:

如果IE,直接註冊onresize(這個點贊啊)

否則: 建立 type為text/html的object

設定position為absolute, 高度100%, 寬度100% (這樣可以獲得父容器的寬高)

設定pointer-events:none,利用點選穿透(讓object窗體變成幽靈)

object元素的高度變化後,通知訂閱者

resize事件節流

問題:

  1. 建立object
  2. 事件處理函式掛載了元素本身上

javascript-detect-element-resize

建立三個子元素,利用scroll事件來監測變化。

原理:

https://zhuanlan.zhihu.com/p/24887312
The scroll event is fired when the document view or an element has been scrolled.
當文件檢視或者元素滾動的時候會觸發 scroll 事件。
也就是說元素滾動的時候會觸發這個事件,那麼什麼時候元素會滾動?當元素大於其父級元素,且父級元素允許其滾動的時候,該元素可以進行滾動。
換句話說,元素可以滾動意味著父子元素大小不一致,這是這個方法的核心。
那麼我們需要讓元素大小發生改變時,使得 scrollLeft 或者 scrollTop 發生改變,從而觸發 scroll 事件,進一步得知其大小發生了改變。

visibility: hidden; opacity: 0; position: absolute;讓自己變得虛無

addEventListener("scroll", scrollListener, true) 在捕捉階段攔截事件,使用false無效

div.expand-trigger 變大

div.expand-trigger 變小

animationstart來監聽顯示,比如style.display = 'none'然後style.display = 'block'

問題:

  1. 額外建立四個元素節點以及一個style節點
  2. 事件都掛載了元素本身身上,

ResizeObserver

原生自帶的方案, 相容性並不高, resize-observer-polyfill 基於resize和MutationOberver的polyfill實現了ResizeObserver。

 const resizeObserver = new ResizeObserver(entries => {
        for (let entry of entries) {
            
            console.log(entry.target.id, `height:${entry.contentRect.height}  width:${entry.contentRect.width}`);
        }
        });
        resizeObserver.observe(document.querySelector('#my_element'));
        resizeObserver.observe(document.querySelector('#my_element2'));

此外

當然,我覺得還

  1. 定時器 + getComputedStyle 也是很低成本的實現。
  2. resize + MutationOberver 也是很簡單的方案。

相關文章