有時候我們會需要偵測頁面上是否有新增的DOM,最簡單的做法是直接去listen DOMNodeInserted
事件,但這方法雖然簡單卻會大幅度的影響效能(由其是頁面DOM元素多的時候),也因此MDN不建議這樣使用。
沒辦法直接listen dom event那要怎麼搞?Daniel Buchner提出了一種hack,簡略的流程是這樣:針對listening DOM寫個CSS3的animation,讓在DOM建立的時候瀏覽器會生成animationStart
事件,只要抓取到這個事件並且判別該animation為該DOM所產生,就可以知道有新的DOM已經建立了。
直接貼上Buchner的JSFiddle:
詳細解說:(為了方便說明,code跟JSFiddle裡的有點出入)
- 建立animation的keyframe:
animation本身只要讓使用者看不出來就好,這裡是從clip 1px變成clip 0px。/* set up the keyframes */ @keyframes nodeInserted { from { clip: rect(1px, auto, auto, auto); } to { clip: rect(0px, auto, auto, auto); } } @-moz-keyframes nodeInserted { from { clip: rect(1px, auto, auto, auto); } to { clip: rect(0px, auto, auto, auto); } } @-webkit-keyframes nodeInserted { from { clip: rect(1px, auto, auto, auto); } to { clip: rect(0px, auto, auto, auto); } } @-ms-keyframes nodeInserted { from { clip: rect(1px, auto, auto, auto); } to { clip: rect(0px, auto, auto, auto); } } @-o-keyframes nodeInserted { from { clip: rect(1px, auto, auto, auto); } to { clip: rect(0px, auto, auto, auto); } }
- 套用animation到想要監聽事件的DOM上面(注意是設定在會新增的DOM,而不是他的父元素)
animation-duration設定時間極短也是為了讓使用者不要注意到有animationdiv.some-control { animation-duration: 0.001s; -o-animation-duration: 0.001s; -ms-animation-duration: 0.001s; -moz-animation-duration: 0.001s; -webkit-animation-duration: 0.001s; animation-name: nodeInserted; -o-animation-name: nodeInserted; -ms-animation-name: nodeInserted; -moz-animation-name: nodeInserted; -webkit-animation-name: nodeInserted; }
- Javascript用來監聽事件的code:
var listener = function(event){ if (event.animationName == 'nodeInserted') //新增DOM之後想做的動作寫在這 } document.addEventListener('animationstart', listener , false); document.addEventListener('MSAnimationStart', listener , false); document.addEventListener('webkitAnimationStart', listener , false);
animationstart
,MSAnimationStart
,webkitAnimationStart
分別是不同瀏覽器會產生的事件名稱,事件發生之後就會呼叫listener,進入listener之後還需要判別這個animationName
是不是我們設定的,以免錯抓到別的DOM產生的animationStart事件。 - 基本上還是個hack,不清楚當頁面的animation一多的時候效能如何。
- 瀏覽器必須支援CSS3 Animation,支援列表。
沒有留言:
張貼留言