【问题标题】:How to handle events of dynamic created elements without jQuery or zepto?如何在没有 jQuery 或 zepto 的情况下处理动态创建元素的事件?
【发布时间】:2014-02-19 03:56:41
【问题描述】:

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

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

更新:

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

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);
      });
}

但是不知道jquery是不是这样工作的,我想知道,完成我的功能。

【问题讨论】:

  • 事件传播呢?这样你就不必处理你推入或从 dom 中删除的每个元素的绑定和解除绑定开销?
  • @Newse,毫无疑问,jQuery 和 zepto 使一些事情变得更容易,但想知道如何自己做一些事情当然是值得的。
  • 仅供参考,如果您的 dynamic 在事件绑定后创建元素,jQuery 决定弃用 live() 方法。
  • @naomik - 你是绝对正确的,但事件传播与 jquery 或 zepto 有什么关系。我建议这种技术的原因是因为它可以减轻向每个将动态添加的元素添加事件处理程序的开销。 stackoverflow.com/questions/4616694/…
  • 这家伙写了一些纯js代码,相当于JQuery stackoverflow.com/questions/14237233/…

标签: javascript jquery


【解决方案1】:

这是一个使用 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);

让我们创建一些元素

// 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);

实际使用情况

on("button.hello", "click", function(event) {
  alert("spooked ya!");
  event.preventDefault();
});

值得注意的笔记!

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

【讨论】:

  • 非常感谢,正是我想要的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-03
  • 2016-02-20
  • 1970-01-01
  • 2011-06-04
  • 2016-11-03
  • 2011-07-09
  • 1970-01-01
相关资源
最近更新 更多