javascript - 无法删除 windows 对象的事件侦听器
问题描述
我在尝试删除事件侦听器时遇到了很多麻烦。
我创建了一个非常依赖 JavaScript 的网站。当您在网站上导航时,它基本上是动态加载元素,而无需使用模板文字刷新页面。
我有时必须加载内容并添加无限滚动,但也能够再次删除该事件。
这是我用来处理滚动事件的代码:
var start = 30;
var active = true;
function yHandler(elem)
{
var oHeight = selectElems('content_main', 'i').offsetHeight;
var yOffset = window.pageYOffset;
var hLimit = yOffset + window.innerHeight;
if (hLimit >= oHeight - 500 && active === true)
{
active = false;
new requestContent({
page: GET.page,
type: returnContentType(GET.page),
scroll: true,
start: start
}, (results) => {
if(results){
setTimeout(()=>{
active = true;
start = start + 30;;
}, 400);
new ContentActive();
}
});
}
}
var scrollRoute =
{
contentScroll: () =>{
yHandler();
}
};
var scrollHandler = function(options)
{
var func = options.func.name;
var funcOptions = options.func.options;
var elem = options.elem;
var flag = options.flag;
this.events = () => {
addEvent(elem, 'scroll', ()=>{
scrollRoute[func](elem, funcOptions);
}, flag);
}
this.clear = () => {
elem.removeEventListener('scroll', scrollRoute[func](), flag);
}
}
我正在使用此功能来设置事件
function addEvent(obj, type, fn, flag = false) {
if (obj.addEventListener) {
obj.addEventListener(type, fn, flag);
} else if (obj.attachEvent) {
obj["e" + type + fn] = fn;
obj[type + fn] = function () {
obj["e" + type + fn](window.event);
};
obj.attachEvent("on" + type, obj[type + fn]);
} else {
obj["on" + type] = obj["e" + type + fn];
}
}
当我需要设置无限滚动事件时,我从任何代码中调用此代码
new scrollHandler({
func: {
'name':'contentScroll',
},
elem: window,
flag: true,
}).events();
当我需要删除无限滚动事件但没有任何运气时,我从任何代码中调用此代码
new scrollHandler({
func: {
'name':'contentScroll',
},
elem: window,
flag: true,
}).clear();
如何成功删除事件监听器?我不能只命名实例,从长远来看,在从不同的地方设置和删除滚动事件时会很混乱。
解决方案
Two problems:
You have to pass the same function to
removeEventListener
as you passed toaddEventListener
. (Similarly, you have to pass the same function todetachEvent
as you passed toattachEvent
using Microsoft's proprietary stuff — but unless you really have to support IE8 and earlier, you can ditch all that.) Your code isn't doing that.When trying to remove the handler, you're calling
scrollRoute[func]()
and passing its return value intoremoveEventListener
. As far as I can tell, that's passingundefined
intoremoveEventListener
, which won't do anything useful.
Here's the code I'm referring to above:
this.events = () => {
addEvent(elem, 'scroll', ()=>{ // *** Arrow function you don't
scrollRoute[func](elem, funcOptions); // *** save anywhere
}, flag); // ***
}
this.clear = () => {
elem.removeEventListener('scroll', scrollRoute[func](), flag);
// Calling rather than passing func −−−^^^^^^^^^^^^^^^^^^^
}
Notice that the function you're passing addEvent
(which will pass it to addEventListener
) is an anonymous arrow function you don't save anywhere, but the function you're passing removeEventListener
is the result of calling scrollRoute[func]()
.
You'll need to keep a reference to the function you pass addEvent
and then pass that same function to a function that will undo what addEvent
did (removeEvent
, perhaps?). Or, again, ditch all that, don't support IE8, and use addEventListener
directly.
So for instance:
var scrollHandler = function(options) {
var func = options.func.name;
var funcOptions = options.func.options;
var elem = options.elem;
var flag = options.flag;
var handler = () => {
scrollRoute[func](elem, funcOptions);
};
this.events = () => {
elem.addEventListener('scroll', handler, flag);
};
this.clear = () => {
elem.removeEventListener('scroll', handler, flag);
};
};
(Notice I added a couple of missing semicolons, since you seem to be using them elsewhere, and consistent curly brace positioning.)
Or using more features of ES2015 (since you're using arrow functions already):
var scrollHandler = function(options) {
const {elem, flag, func: {name, options}} = options;
const handler = () => {
scrollRoute[name](elem, options);
};
this.events = () => {
elem.addEventListener('scroll', handler, flag);
};
this.clear = () => {
elem.removeEventListener('scroll', handler, flag);
};
};
推荐阅读
- access-denied - SQLSTATE[HY000] [1045] 用户 'rentacar'@'localhost' 的访问被拒绝(使用密码:YES)
- python - 散点图矩阵
- python - 在具有基于其他列的条件的列中添加值,仅获取输入的最后一个值
- linux - 使用 mailx 发送邮件时的输出格式
- ssl - 为什么我的 QuoVadis 证书在 Java 应用程序中无效?
- python-3.x - 下载带有请求的 zip 文件时,文件最终被损坏
- sql - ORACLE 使用 TO_DATE 检查项目是否在最后一小时内
- laravel - Uncaught SyntaxError: Unexpected token '<' in app.js in Gcloud
- android - 使用 ActivityResultLauncher 请求 WRITE_EXTERNAL_STORAGE 时出现 ArrayOutOfBounds 异常
- node.js - 我想在 actions.json 中再添加一个对话