要素のイベントはデフォルトでバブリングされるので、windowでイベントを拾うというのが一般的な方法です。
ちなみにjQueryでの動的要素へのイベント設定もこの仕組みを使っています。
window.addEventListener('click', evt => {
if(evt.target.classList.contains('foo')) {
console.log("FOO↑↑↑");
}
});
別解としては、MutationObserverを使用する方法があります。
しかし、APIの性質上、シンプルさに欠けてしまいます。
あと、IEは11からでしか実装されていないというところも欠点です。
ですが、前述のwindowでイベントを拾うのと違い、その要素自身にイベント設定できる(イベントフェーズの設定もできる)ところが利点です。
function fooClick(evt) {
console.log("FOO↑↑↑");
}
function mutationObjectCallback(records) {
records.forEach(record => {
// if(record.type === 'childList') ...// 基本的にはtypeをチェックしますが、今回はchildListのみ指定してるので省略
(record.addedNodes || []).forEach(node => {
if(node.classList.contains('foo')) {
node.addEventListener('click', fooClick);
}
});
});
}
var observer = new MutationObserver(mutationObjectCallback);
observer.observe(document.body, {childList: true, subtree: true});