我有一个包含多个事件侦听器的导航: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);
}