javascript - 我是否正确地将我的 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));
解决方案
等效的 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));
推荐阅读
- google-bigquery - BigQuery:为什么当我尝试执行查询时给我错误 Not found: Dataset was not found in location US
- geoserver - 在 Geoserver 2.15.1 中加载 sld 栅格样式时出现问题
- mysql - 性能最佳的 MySQL 搜索文本
- nginx - 我无法从我的 Kubernetes 主集群访问 pod
- windows - 我无法在 VBScript 中设置 ADS_UF_PASSWD_CANT_CHANGE 标志
- c++ - 在 MSVC C++ 中强制循环展开
- python - 使用 MongoDB 的 Python DIScordbot
- dictionary - Kotlin 从不可变映射和附加键值创建新映射的标准方法
- reactjs - 电子再热更新状态白屏
- javascript - svg stroke-dasharray 没有工作