首页 > 解决方案 > 我是否正确地将我的 Jquery 事件侦听器转换为 Javascript?我不明白 Javascript 是如何在不定位 id 的情况下工作的?

问题描述

我正在尝试将 jquery 转换为 javascript。我的应用程序是一个简单的待办事项列表,我的目标是一个 ID 为 #clear-completed 的按钮。每当我在我的应用程序上单击该按钮时,它都会删除已完成的待办事项,但我不明白它在我的新 Javascript 代码中的目标位置。

这是原始的Jquery代码

$('#footer').on('click', '#clear-completed', this.destroyCompleted.bind(this));

所以我把它改成了 Javascript 并且这段代码有效

var footer = document.getElementById('footer');
      footer.addEventListener('click', this.destroyCompleted.bind(this))

我不明白#clear-completed id 发生了什么以及我的新javascript代码如何仍然有效,即使我没有指定定位#clear-completed 按钮?

这是destroyCompleted函数的代码

destroyCompleted: function () {
            this.todos = this.getActiveTodos();
            this.filter = 'all';
            this.render();
        },

在调试器中,它通过 activeTodos 函数运行,但我没有看到 id #clear-completed 的目标位置?

getActiveTodos: function () {
            return this.todos.filter(function (todo) {
                return !todo.completed;
            });
        },
        getCompletedTodos: function () {
            return this.todos.filter(function (todo) {
                return todo.completed;
            });
        },

我是否将我的 Jquery 正确地写入了 Javascript?还是我错过了什么?

此外,如果 id 有多个事件侦听器,您将如何正确编码?例如

$('#todo-list')
                .on('change', '.toggle', this.toggle.bind(this))
                .on('dblclick', 'label', this.edit.bind(this))
                .on('keyup', '.edit', this.editKeyup.bind(this))
                .on('focusout', '.edit', this.update.bind(this))
                .on('click', '.destroy', this.destroy.bind(this));

标签: javascriptjquery

解决方案


等效的 JavaScript 将是:

document.querySelector('#footer').addEventListener('click', event => {
  const element = event.target.closest('#clear-completed');

  if (
    event.currentTarget !== element && 
    event.currentTarget.contains(element)
  ) {
    this.destroyCompleted(event);
  }
});

$(target).on(event, selector, handler)您正在使用的签名称为委托事件处理程序,因此在您正确复制handler的元素上调用target,但仅当事件以匹配的元素为目标时调用它,该元素selector是 的后代target,不包括target其自身。

通过检查.event.currentTarget .contains()event.target .closest(selector)

您甚至可以将此逻辑分解为辅助函数以使其更具可读性:

document.querySelector('#footer').addEventListener('click', event => {
  const matches = selector => {
    const element = event.target.closest(selector);

    return (
      event.currentTarget !== element &&
      event.currentTarget.contains(element)
    );
  };

  if (matches('#clear-completed')) {
    this.destroyCompleted(event);
  }
});

由于您多次需要此模式,因此将其移至另一个可重用函数中是有意义的:

function delegate (target, type, selector, handler) {
  const matches = event => {
    const element = event.target.closest(selector);

    return (
      event.currentTarget !== element &&
      event.currentTarget.contains(element)
    );
  };

  target.addEventListener(type, event => {
    if (matches(event)) {
      handler(event);
    }
  });
}

const element = document.querySelector('#todo-list');

delegate(element, 'change', '.toggle', e => this.toggle(e));
delegate(element, 'dblclick', 'label', e => this.edit(e));
delegate(element, 'keyup', '.edit', e => this.editKeyup(e));
delegate(element, 'focusout', '.edit', e => this.update(e));
delegate(element, 'click', '.destroy', e => this.destroy(e));

推荐阅读