removeEventlistener无法按预期使用箭头函数和参数

时间:2017-02-08 11:05:45

标签: javascript ecmascript-6

我有一个可以容纳多个可编辑内容的页面。我想在编辑内容时发出某种检查事件。

我的代码实现如下:

// Find all editable elements.
let allEditableElements = document.querySelectorAll('[contenteditable="true"]');

for(let i = 0; i < allEditableElements.length; i++){

  //Remove eventListener to prevent duplicate events.
  allEditableElements[i].removeEventListener('input', (event) => {myClass.myEventMethod(event);}, false);

  // Add event.
  allEditableElements[i].addEventListener('input', (event) => {myClass.myEventMethod(event);}, false);
} 

到目前为止一切正常。但正如我所说,用户可以编辑内容,包括向页面本身添加新的可编辑内容。此时将重新设置事件,这就是我之前尝试删除event的原因。

我的问题是为什么removeEventListener功能无法正常工作?并且没有办法为这些事件命名如此:

// With eventNameGivenByUser an event could be removed just by its name.
addEventListener('eventTriggerName', 'eventNameGivenByUser', function(), [, options]);

当然我做了一些研究,发现代码本身就是这样的:

// Find all editable elements.

let allEditableElements = document.querySelectorAll('[contenteditable="true"]');

for(let i = 0; i < allEditableElements.length; i++){

  //Remove eventListener to prevent duplicate events.
  allEditableElements[i].removeEventListener('input', myClass.myEventMethod, false);

  // Add event.
  allEditableElements[i].addEventListener('input', myClass.myEventMethod, false);
} 

但是这没有传递参数,这在动态设置中是必需的......

希望有人能告诉我,2017年有一种不错的方式而且不使用图书馆。

编辑08.02.2017:

只为好奇的人: 解决方案是不将任何参数传递给侦听器:

// as you can see there is no (event) and no arrow function either.
addEventListener('input', myClass.myEventMethod, false);

现在要做的就是调用这样的方法:

// The Parameter will be passed through anyway!
myEventMethod(event) {

      /**
      * Do stuff with event parameter.
      */

};

之后,可以像这样删除监听器:

removeEventListener('input', myClass.myEventMethod, false);

旁注:

我使用电子而不需要跨浏览器支持。它必须与Chromium: 56.0.2924.87兼容。

此致,Megajin

2 个答案:

答案 0 :(得分:3)

removeEventListener方法至少需要两个参数:事件名称和要删除的侦听器函数。

在你的第一个例子中:

  allEditableElements[i].removeEventListener('input', (event) => {myClass.myEventMethod(event);}, false);

您正在定义一个以前未附加为事件监听器的新功能,因此无法将其删除。

我不知道你的第二次尝试有什么问题:

allEditableElements[i].removeEventListener('input', myClass.myEventMethod, false);

这个应该可以正常工作。但是,您可以将两种方法结合起来:将类方法包装在函数中,并将包装的版本作为侦听器附加。您只需要有一个参考,以便以后删除:

const inputListener = (event) => { myClass.myEventMethod(event); };
let allEditableElements = document.querySelectorAll('[contenteditable="true"]');


for(let i = 0; i < allEditableElements.length; i++){

  //Remove eventListener to prevent duplicate events.
  allEditableElements[i].removeEventListener('input', inputListener, false);

  // Add event.
  allEditableElements[i].addEventListener('input', inputListener, false);
} 

所有说我建议只使用事件委派。将侦听器附加到DOM中较高的元素上,并且在出现新元素时不必担心清除和重新添加事件侦听器:

const handleContentEditable = e => {
    if( e.target.isContentEditable ){
        console.log( 'editing ', e.target );
    }
};

document.body.addEventListener('input', handleContentEditable );

https://jsfiddle.net/rd3y9gh9/1/

答案 1 :(得分:2)

这是因为removeEventListener中的箭头函数正在创建一个新的函数引用。 removeEventListener需要引用传递给addEventListener的原始方法。

您必须在案例中保留对事件方法的引用,或者您可以动态地重新创建输入元素,这将删除所有事件侦听器。

https://developer.mozilla.org/en/docs/Web/API/Node/cloneNode

克隆节点不会复制事件侦听器,因此您可以使用它来克隆原始元素并替换它。