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

时间:2017-02-08 14:05:54

标签: javascript html dom listener

我想从元素中删除一个事件侦听器,然后再将其分配回来。有没有办法得到它并存储在像var storedListener = Element.getEventListener('click')这样的变量smth中,以便稍后我可以做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>取代Collection .update({ "_id": ObjectId("589b043abc2f5a467c13303b") }, { "$pull": { "items": { "_id": ObjectId("589b043abc2f5a467c13303c") } } }); 并将父public int GetId(int fkId) { const string sql = @"SELECT * FROM myTable WHERE myForeignKey = @fkId"; using (var conn = _connectionHelper.GetConnection()) { return conn.Query<int>(sql, new { fkId }).First(); } } 带入其中$.ajax({ method: 'post', url: targetFile , data: {data: text}, dataType: "json", success: function(response){ $.each(response, function(element){ $("#"+element.name).text(element.text); }); } }); 原来的听众回来了。

3 个答案:

答案 0 :(得分:2)

你得到的有点错误......没有可从JavaScript访问的事件监听器列表......你唯一能做的就是在你知道原点的情况下删除/添加一个事件。

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

  1. 的addEventListener(EVENT_TYPE,函数);
  2. removeEventListener(EVENT_TYPE,函数);
  3. 一个对象可以有多个相同类型的事件......区分它们的唯一方法是给出一个被调用的精确函数。

    请注意,如果它是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);
        }
    }
    

答案 1 :(得分:2)

要删除添加了.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-属性,而不是处理事件,表示它已打开。然后,如果该属性不存在,您只需修改内部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/

答案 2 :(得分:1)

不,自.getEventListener is only available for debugging purposes以来这是不可能的。 遗憾的是,标准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);