EagleLand

2013.05.07

DOMイベントのバブリングについて

最近はプロジェクトの異動やらなんやらで非常にドタバタしてまして、中々調べものとかに没頭出来ていない。そんな異動先のプロジェクトでイベントのバブリングについて再考したので覚書。

イベントのバブリング?

イベントは発火元のノードから、親のノードにどんどん伝播していく。親のノードで発火元のイベントを拾う事が出来る。

バインドのターゲットと発火順

以下のような記述を見つけた。

window.addEventListener('DOMContentLoaded', function() {
  console.log('document is ready.');
});

windowにバインドされてる。バブリングすることを考えれば納得出来るが、意図はわからないまま…。

window.addEventListener('load', function(e) {
  console.log('window:load');
});

window.addEventListener('DOMContentLoaded', function(e) {
  console.log('window:DOMContentLoaded');
});

document.addEventListener('DOMContentLoaded', function(e) {
  console.log('document:DOMContentLoaded');
});

実行すると、

document:DOMContentLoaded
window:DOMContentLoaded
window:load

という順で出力される。

イベントの正体

次のイベントオブジェクトの中身を見てみる。

var windowDomReady = null;
var documentDomReady = null;

window.addEventListener('load', function(e) {
  console.log(windowDomReady === documentDomReady);
});

window.addEventListener('DOMContentLoaded', function(e) {
  windowDomReady = e;
});

document.addEventListener('DOMContentLoaded', function(e) {
  documentDomReady = e;
});

実行してみると、

true

と。イベントのtypeもDOMContentLoadedだし、targetもdocumentだった。ということは、

window.addEventListener('DOMContentLoaded', function(e) {
  console.log('window:DOMContentLoaded');
});

document.addEventListener('DOMContentLoaded', function(e) {
  console.log('window:DOMContentLoaded');
  e.stopPropagation();
});

window:DOMContentLoadedは出力されなかった。このように、イベントの伝播はe.stopPropagation()で止める事ができる。 cancelBubbleプロパティにtrueを与えても伝播を止める事ができるが、こちらは非標準なので、stopPropagation()を使うのが適切と言える。

もちろん他のイベントでも

window.addEventListener('DOMNodeInserted', function(e) {
  console.log('window:DOMNodeInserted');
});

document.addEventListener('DOMNodeInserted', function(e) {
  console.log('document:DOMNodeInserted');
});

window.addEventListener('load', function(e) {
  var element = document.createElement('div');
  element.innerHTML = 'ほげ';
  document.body.appendChild(element);
});

実行すると、

document:DOMNodeInserted
window:DOMNodeInserted

伝播している。jQueryなどで実装されているイベントのdelegateは、このイベントの伝播する性質を利用して実装している。

でも結局・・・

なんでwindowで拾っているのかはわからなかった…(´・ω・`)

タイトルと URL をコピーしました