litelement - 处理点击离开事件

litelement - handling click away event

我正在使用 litelement 构建站点导航。它将有一个下拉菜单。我想弄清楚如何添加一个事件,以便如果用户单击下拉菜单本身以外的任何地方,甚至是自定义元素之外的任何地方,下拉菜单都会关闭。我认为这是自然的期望。

我想在我的自定义元素中添加一个 属性,它可以用作 "state"。然后通过 connectedCallback 生命周期方法向文档添加事件监听器。但是,似乎我无法像预期的那样真正访问 属性 。 属性 可通过附加了事件的任何其他元素访问。

下面是一个非常通用的codepen。单击文档上的任意位置应该会打开一个弹出窗口,其中显示 属性 的值未定义。但是,如果我单击自定义元素内的按钮,该按钮附加了一个事件,则该事件处理程序能够成功访问 属性。

https://codepen.io/aver-mimas/pen/ExjZXMq

这个例子出了什么问题?

在你的 codepen 中发生的事情是,当你将一个成员函数作为参数发送给将存储它并稍后使用它的东西时(事件监听器将把函数存储在一个内部变量中,并在event is fired) 在JS中,这个成员函数"loose" this 属性。 它没有链接到 lit-element,而是链接到 js 本身,并且可以在各种情况下发生,但是 lit-element 创造了很多可以变得相关的情况。

您可以使用

document.addEventListener('click', e=>this.handleDocumentClick())

而不是

document.addEventListener('click', this.handleDocumentClick)

箭头函数会指示JS绑定声明它的对象的'this',然后用正确的上下文调用成员函数。

虽然在添加事件侦听器时将点击处理程序包装在匿名函数中效果很好,但删除它(您通常应该这样做)将不起作用。原因是这两个匿名函数虽然看起来一模一样,但是它们的引用却完全不同。

document.addEventListener('click', e => this.handleDocumentClick());
document.removeEventListener('click', e => this.handleDocumentClick()); // ❌ doesn't work

因此,在这种情况下,您应该在 class 中使用箭头函数,如 docs:

中所述
const handleDocumentClick = () => {
  // handle click event
};

// ..

document.addEventListener('click', this.handleDocumentClick);
document.removeEventListener('click', this.handleDocumentClick); // ✅ works