javascript - 使用回调函数和参数添加和删除 eventListener
问题描述
我有一个带有多个事件侦听器的导航:click
和hover
. 此事件侦听器可以更改,例如在浏览器调整大小时。我在自己的方法中添加事件侦听器,如果应该重新初始化侦听器,则会调用该方法。我在以下课程中的问题:removeEventListener
不起作用。因此,重新初始化会导致两者都click
发生hover
火灾。
class Navigation {
constructor(element) {
this.element = element;
this.changeButton = this.element.querySelector("button");
this.version = "hover";
this.navItemElements = Array.from(this.element.querySelectorAll(".nav-item"));
this.navItems = this.createNavItems(this.navItemElements);
this.clickHandler = (event) => this.navItemHoverHandler(event);
this.changeButton.addEventListener("click", () => {
this.isHoverVersion = !(this.isHoverVersion);
console.log("Change trigger. Is hover version --> " + this.isHoverVersion);
this.initListeners();
});
this.clickHandler = (event, navItem) => this.navItemClickHandler(event, navItem);
this.hoverHandler = (event, navItem) => this.navItemHoverHandler(event, navItem);
this.initListeners();
}
initListeners() {
console.log("Init listeners");
console.log(this.navItems);
if (this.isHoverVersion) {
this.navItems.forEach((navItem) => {
console.log(navItem);
navItem.link.addEventListener('mouseover', e => this.hoverHandler(e, navItem));
navItem.link.addEventListener('mouseout', e => this.hoverHandler(e, navItem));
navItem.link.removeEventListener('click',this.clickHandler);
})
} else {
this.navItems.forEach((navItem) => {
navItem.link.addEventListener('click', e => this.clickHandler(e, navItem));
navItem.link.removeEventListener('mouseover', this.hoverHandler);
navItem.link.removeEventListener('mouseout', this.hoverHandler);
})
}
}
navItemClickHandler(event, navItem) {
event.preventDefault();
console.log('Click handler executed');
console.log(navItem);
}
navItemHoverHandler(event, navItem) {
event.preventDefault();
console.log('Hover handler executed');
console.log(navItem);
}
createNavItems(navItemElements) {
let navItems = [];
navItemElements.forEach((itemElement) => {
navItems.push(this.createNavItemObject(itemElement));
});
return navItems;
}
createNavItemObject(navItem) {
let container = navItem;
let link = navItem.querySelector("a");
return {
container: container,
link: link,
};
}
}
let navigationElement = document.querySelector(".navigation");
new Navigation(navigationElement);
.navigation {
display: flex;
flex-flow: row nowrap;
width: 100%;
justify-content: space-between;
width: 100%;
max-width: 280px;
}
ul {
display: flex;
flex-flow: row nowrap;
list-style: none;
margin: 0;
padding: 0;
}
li {
margin-right: 20px;
}
<div class="navigation">
<button id="changeButton">Change trigger</button>
<ul>
<li class="nav-item">
<a href="">Link 1</a>
</li>
<li class="nav-item">
<a href="">Link 2</a>
</li>
</ul>
</div>
navItem
是我之前创建的对象。navItem.link
是 HTML 锚元素。
问题:
如何将侦听器绑定到特定对象?我需要调用相同的方法,但使用它的特定navItem
对象......
更新:
添加了工作代码示例。导航通过点击触发器进行初始化。单击按钮将切换单击/悬停。在此示例中,从单击切换到悬停后,两个侦听器都会执行。
解决方案
您需要使用您使用的确切功能addEventListener
,查看MDN 上的说明。
因此,在您的示例中,您定义了一个新的匿名函数:
navItem.link.addEventListener('mouseout', e =>
this.hoverHandler(e, navItem)
);
箭头函数是新的匿名函数:e => ...
. 因此,您需要使用完全相同的函数,而不是使用这个匿名函数。
要获取navItem
事件处理程序,您可以使用bind()
. bind 的第一个参数定义this
事件处理程序中的上下文 ( ),所有其他参数都在任何提供的参数之前(在本例中为event
参数)。但是您应该注意,每次都会bind()
创建一个新的函数引用,因此您需要保存引用以供删除。实现此目的的一种方法是将函数保存在. 对于事件,它将是:navItem
hover
if (this.isHoverVersion) {
this.navItems.forEach(navItem => {
// save function
navItem.hoverHandler = this.navItemHoverHandler.bind(null, navItem);
navItem.link.addEventListener('mouseover', navItem.hoverHandler);
navItem.link.addEventListener('mouseout', navItem.hoverHandler);
});
} else {
this.navItems.forEach(navItem => {
navItem.link.removeEventListener('mouseover', navItem.hoverHandler);
navItem.link.removeEventListener('mouseout', navItem.hoverHandler);
});
}
此外,您需要将您的更改navItemHoverHandler
为:
navItemHoverHandler(navItem, event) { // reversed order
event.preventDefault();
console.log('Hover handler executed');
console.log(navItem);
}
推荐阅读
- html - selenium - 使用包含 sup 标签的 span 文本创建 xpath
- postgresql - 如何在 POstgresql 中对不同表的值求和?
- google-cloud-sql - 使用 SSL 连接到 Cloud SQL
- c# - 我怎样才能通过 LIST
在 C# 中作为消息发送到 pubsub - php - MariaDB 服务器版本,用于在第 1 行的 '14:24:56 LIMIT 0, 25' 附近使用正确的语法
- android-intent - 如何在 Kotlin 中使用 Intent.ACTION_DIAL
- javascript - 如何将字体真棒图标动态添加到类元素?
- aurelia - 如何使用 aurelia 在 ag-grid 中显示行号?
- c++ - 通过撤消琐碎的更改来最小化 git diff
- powershell - 如何为我的 PowerShell 函数编写 Pester 测试