我有一个导航,其中包含多个事件侦听器: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
对象...
更新:
添加了工作代码示例。 导航通过点击触发器进行初始化。点击按钮将切换点击/悬停。在此示例中,从单击切换到悬停后,两个侦听器均被执行。
答案 0 :(得分:1)
您需要使用在addEventListener
中使用的确切功能,请检查explanation on MDN。
因此在您的示例中,您定义了一个新的匿名函数:
navItem.link.addEventListener('mouseout', e =>
this.hoverHandler(e, navItem)
);
箭头功能是新的匿名功能:e => ...
。因此,代替使用此匿名函数,您需要使用完全相同的函数。
要在事件处理程序中获取navItem
,可以使用bind()
。 bind的第一个参数定义事件处理程序中的上下文(this
),而所有其他参数在提供的所有参数之前(在本例中为event
参数)。但是您应该注意,bind()
创建了一个新的function reference every time,因此您需要保存删除引用。一种实现方法是将函数保存在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);
}