gpt4 book ai didi

javascript - removeEventListener 没有按预期工作

转载 作者:行者123 更新时间:2023-11-30 15:00:54 26 4
gpt4 key购买 nike

我的 Vue 应用程序中有一个相当简单的组件。当用户打开菜单时,我将事件监听器添加到 #app 元素以检测“外部”点击。

当用户在外部单击时,它会关闭菜单并移除事件监听器。这按预期工作。问题是,当用户单击按钮打开菜单,然后再次单击它关闭它时,我想要removeEventListener 因为菜单现在已关闭.

然而,这是行不通的。当我通过按钮打开菜单然后通过按钮关闭它时,事件监听器保留在 #app 元素上,即使我正在删除它也是如此。

如果您多次单击按钮,然后在值显示 true 时单击按钮外部,您将多次看到控制台日志 outside click

new Vue({
el: "#app",
data: {
menuVisible: false
},
methods: {
click(e) {
var clickSource = e.target;
var app = document.getElementById("app");
var that = this;

function clickOutside(e) {
if (e.target != clickSource) {
console.log("outside click");
that.menuVisible = false;
app.removeEventListener("click", clickOutside);
}
}

if (this.menuVisible === false) {
this.menuVisible = true;
app.addEventListener("click", clickOutside);
} else if (this.menuVisible === true) {
this.menuVisible = false;
app.removeEventListener("click", clickOutside);
}
}
}
});
body {
margin: 0;
}

#app {
min-height: 100vh;
}
<script src="https://unpkg.com/vue"></script>

<div id="app">
{{menuVisible}}
<button @click="click">
click
</button>
</div>

最佳答案

问题是在每次点击时,您都会创建一个 clickOutside 函数;如果您将该函数与 removeEventListener 一起使用,因为没有向该确切 函数对象注册事件,所以不会删除任何内容。

相反,请记住处理程序对象,以便您可以使用它进行删除,请参阅注释:

new Vue({
el: "#app",
data: {
menuVisible: false,
clickOutside: null
},
methods: {
click(e) {
var clickSource = e.target;
var app = document.getElementById("app");
var that = this;

// Only create it if we don't already have it
if (!this.clickOutside) {
// Create it
this.clickOutside = function clickOutside(e) {
console.log("clickOutside triggered");
if (e.target != clickSource) {
console.log("It's an outside click");
that.menuVisible = false;
// Remove it
app.removeEventListener("click", that.clickOutside);
}
};
}

if (this.menuVisible === false) {
this.menuVisible = true;
app.addEventListener("click", this.clickOutside);
} else if (this.menuVisible === true) {
this.menuVisible = false;
app.removeEventListener("click", this.clickOutside);
}
}
}
});
body {
margin: 0;
}

#app {
min-height: 100vh;
background-color: #ddd;
}
<script src="https://unpkg.com/vue"></script>

<div id="app">
{{menuVisible}}
<button @click="click">
click
</button>
</div>


旁注:使用起来更加地道

if (this.menuVisible) {
this.menuVisible = false;
app.removeEventListener("click", this.clickOutside);
} else {
this.menuVisible = true;
app.addEventListener("click", this.clickOutside);
}

甚至

this.menuVisible = !this.menuVisible;
if (this.menuVisible) {
app.addEventListener("click", this.clickOutside);
} else {
app.removeEventListener("click", this.clickOutside);
}

...而不是将 bool 值与 truefalse=== 进行比较。您已经了一个 bool 值,所以...我的意思是,您在哪里停止? if ((this.menuVisible) === true === true)? :-)

关于javascript - removeEventListener 没有按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46546472/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com