添加和删除带有回调函数和参数的eventListener



我有一个包含多个事件侦听器的导航:clickhover。此事件侦听器可以更改,例如在调整浏览器大小时。我在自己的方法中添加了事件侦听器,如果应该重新初始化侦听器,就会调用该方法。我在下一节课上的问题是:removeEventListener不起作用。因此,重新初始化会导致clickhover同时启动。

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);
}

最新更新