繁体   English   中英

获取元素事件侦听器并将其存储

[英]Get element event listener and store it

我想从元素中删除事件侦听器,然后再将其分配回去。 有没有一种方法来获取它并存储在像var storedListener = Element.getEventListener('click')一样的变量smth中,如var storedListener = Element.getEventListener('click') ,这样以后我就可以执行Element.addEventListener('click', storedListener)这样的事情了?

更新

侦听器在模板内部分配,我使用Angular 2。

<div *ngFor="let entry of data; let i=index">
  <div class="element-description" (click)="editElementDescription(i)">{{entry.description}}</div>
</div>

我想要做的是单击它后将<div>内部的内容设置为<input> ,以便更改值并将其发送到服务器。 editElementDescription()内部,执行以下操作:

public editElementDescription(index: number): void {
    var elementDescription: HTMLDivElement = <HTMLDivElement>document.getElementsByClassName('element-description')[index];
    elementDescription.removeEventListener('click');
    elementDescription.innerHTML = '<input id="change-description-input" type="text" value="' + elementDescription.innerHTML + '"/>';
  }

我删除了该click侦听器,因为如果再单击一次<input>内容,它将获得该innerHTML 因此,我们的想法是为该<input>元素分配一个change侦听器,该侦听器将用它的值替换<input>并将其父<div>用作其原始侦听器。

您将其弄错了...没有可从JavaScript访问的事件侦听器列表...您唯一可以做的就是在知道来源的情况下删除/添加事件。

有两个函数可以操作事件侦听器:

  1. addEventListener(event_type,function);
  2. removeEventListener(event_type,function);

一个对象可以具有多个相同类型的事件...区别它们的唯一方法是通过调用一个确切的函数。

请注意,如果它是jQuery ,则可以,因为它具有自己的事件堆栈...下面的示例:

var events = $("#object1").data('events');
var $object2 = $("#object2");
if (events) {
    for(var eventType in events){
        for(var idx in events[eventType]){
            $object2[eventType](events[eventType][idx].handler);
        }
        $('#object1').off(eventType);
    }
}

为了删除添加了.addEventListener()的侦听.addEventListener() ,您必须跟踪侦听器函数引用,并稍后使用.removeEventListener()删除它。

像这样:

var btn = document.getElementById('btn');
var btn_add = document.getElementById('btn-add-listener');
var btn_remove = document.getElementById('btn-remove-listener');

var fnListener =  function(e) {
    alert('Clicked!');
};


btn_add.addEventListener('click', function() {
    btn.addEventListener('click', fnListener);
});

btn_remove.addEventListener('click', function() {
    btn.removeEventListener('click', fnListener);
});

工作演示: https//jsfiddle.net/mrlew/k5m1nog3/


其他方法(在问题更新后添加)

考虑到您的实际问题,我建议采用另一种方法:除了处理事件之外,还可以在元素中设置一个data- attribute属性以指示其已打开。 然后,如果属性不存在,则只需修改内部HTML。

像这样:

function editElementDescription(index) {

    var elementDescription = document.getElementsByClassName('element-description')[index];

    var isOpen = elementDescription.getAttribute('data-isOpen');

    if (!isOpen) {
      elementDescription.setAttribute('data-isOpen', 'true');
      elementDescription.innerHTML = '<input id="change-description-input" type="text" value="' + elementDescription.innerHTML + '"/>';

    }

}

工作演示: https//jsfiddle.net/mrlew/e0yrL08v/

不,这是不可能的,因为.getEventListener仅可用于调试目的 不幸的是,标准JavaScript中没有办法以编程方式取回附加到对象的EventListeners ,并且任何试图实现此目的的库都将依赖不稳定的非标准接口,该接口可能会在一天中停产。

因此,如果您的目标是操纵无法控制的库添加的侦听器,那么您将很不走运。
另一方面,如果您控制环境,那么如果您要将同一个侦听器附加到多个对象,则可以存储对附加回调的引用,或者之后使用.removeEventListener将其删除。

实际上,您可以在页面上没有任何其他内容运行之前先猴子补丁EventTarget.prototype.addEventListener以支持此功能,这对于您遇到的任何问题来说并不是一个很干净的解决方案,但是如果您确实需要,可以快速解决它的实现不完善(不支持useCapture参数):

// getEventListener polyfill, run this before anything else on your page.
(function monkeyPatchGetEventListeners(EventTarget) {

  const eventListeners = new WeakMap();

  const origAddEventListener = EventTarget.prototype.addEventListener;
  EventTarget.prototype.addEventListener = function patchedAddEventListener(eventType, listener, ...args) {
    let allListeners;
    if (eventListeners.has(this)) {
      allListeners = eventListeners.get(this);
    } else {
      allListeners = new Map();
      eventListeners.set(this, allListeners);
    }

    let listeners;
    if (allListeners.has(eventType)) {
      listeners = allListeners.get(eventType);
    } else {
      listeners = [];
      allListeners.set(eventType, listeners);
    }

    listeners.push(listener);
    return origAddEventListener.call(this, eventType, listener,...args);
  }

  const origRemoveEventListener = EventTarget.prototype.removeEventListener;
  EventTarget.prototype.removeEventListener = function patchedRemoveEventListener(eventType, listener, ...args) {
    const call = () => origRemoveEventListener(eventType, listener, useCapture, ...args);
    const allListeners = eventListeners.get(this);
    if (!allListeners) { return call(); }
    const listeners = allListeners.get(this);
    if (!listeners) { return call(); }
    const index = listeners.indexOf(listener);
    if (index === -1) { return call(); }
    index.splice(index, 1);
    return call();
  }

  EventTarget.prototype.getEventListeners = function patchedGetEventListeners(eventType) {
    const allListeners = eventListeners.get(this);
    return allListeners && allListeners.get(eventType);
  }
})(EventTarget);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM