如何在没有jQuery或zepto的情况下处理动态创建元素的事件?

gui*_* 桂林 1 javascript jquery

我知道jquery或zepto $(selctor).on(event, handler)会触发动态创建元素的事件.但我不使用jquery和zepto.我想从头开始编写我的代码,用于学习和轻量级.

我的代码中有很多sth.innerHTML=blablasth.appendChild(..)片段.我必须将事件绑定到它们.

更新:

我想要一个像这样的简单函数,

function $on(selector, eventType, handler) {
    document.querySelectAll(selector).forEach(function(el) {
        el.addEventListener(eventType, handler);
    });
    // on new DOM insert or replaced, let us call it newDom
      newDom.querySelectAll(selector).forEach(function(el) {
          el.addEventListener(eventType, handler);
      });
}
Run Code Online (Sandbox Code Playgroud)

但我不知道jquery是否像这样工作,我想知道它,并完成我的功能.

Tha*_*you 5

以下是使用MDN文档推荐的较新MutationObserver的示例.

这取决于尚未得到广泛支持的Element.prototype.matches.但是,我创建了一个小包装器,以便更容易使用.

DEMO

// live listener function
(function(window) {

  // Element.matches "polyfill"
  (function(e){
    if (typeof e.matches !== "function") {
      e.matches = e.webkitMatchesSelector ||
                  e.mozMatchesSelector    ||
                  e.msMatchesSelector     ||
                  e.oMatchesSelector      ||
                  e.matchesSelector;
    }
  })(Element.prototype);

  function on(selector, eventType, handler) {
    // add listener for all existing elements
    [].forEach.call(document.querySelectorAll(selector), function(elem) {
      elem.addEventListener(eventType, handler);
    });

    // create new "live" observer
    var observer = new MutationObserver(function(records) {
      records.forEach(function(record) {
        [].forEach.call(record.addedNodes || [], function(elem) {
          if (elem.matches(selector)) {
            elem.addEventListener(eventType, handler);
          }
        });
      });
    });

    // watch for DOM changes to body's children and body's subtree
    observer.observe(document.body, {
      childList: true,
      subtree: true
    });

    return observer;
  }

  window.on = on;
})(window);
Run Code Online (Sandbox Code Playgroud)

让我们创建一些元素

// sample button generator
function createButton() {
  var b = document.createElement("button");
  b.className = "hello";
  b.innerHTML = "Spaghett";
  document.body.appendChild(b);
}

// create a new button every second
setInterval(createButton, 1000);
Run Code Online (Sandbox Code Playgroud)

实际用途

on("button.hello", "click", function(event) {
  alert("spooked ya!");
  event.preventDefault();
});
Run Code Online (Sandbox Code Playgroud)

值得注意的笔记!

我正在使用[].forEach.call(..., fn)因为querySelectorAll 没有返回Array.相反,它返回一个NodeList.NodeList对象在其原型链中没有Array.prototype,因此无法直接访问.forEach函数.MutationRecord.prototype.addedNodes也返回一个NodeList.