170

ここに私の問題があります:動的にアタッチされたイベントリスナーの存在を確認することは何とか可能ですか? または、DOM の「onclick」(?) プロパティのステータスを確認するにはどうすればよいですか? Stack Overflow と同じように解決策をインターネットで検索しましたが、うまくいきませんでした。これが私のhtmlです:

<a id="link1" onclick="linkclick(event)"> link 1 </a>
<a id="link2"> link 2 </a> <!-- without inline onclick handler -->

次に、Javascript で、動的に作成されたイベント リスナーを 2 番目のリンクにアタッチします。

document.getElementById('link2').addEventListener('click', linkclick, false);

コードは正常に実行されますが、接続されたリスナーを検出する試みはすべて失敗します。

// test for #link2 - dynamically created eventlistener
alert(elem.onclick); // null
alert(elem.hasAttribute('onclick')); // false
alert(elem.click); // function click(){[native code]} // btw, what's this?

jsFiddle はこちらです。"Add onclick for 2" をクリックしてから "[link 2]" をクリックすると、イベントは正常に発生しますが、"Test link 2" は常に false を報告します。誰か助けてくれませんか?

4

20 に答える 20

65

There is no way to check whether dynamically attached event listeners exist or not.

The only way you can see if an event listener is attached is by attaching event listeners like this:

elem.onclick = function () { console.log (1) }

You can then test if an event listener was attached to onclick by returning !!elem.onclick (or something similar).

于 2012-07-12T15:58:14.463 に答える
28

私がすることは、関数の外にブール値を作成することです。これは、FALSEで始まり、イベントをアタッチするとTRUEに設定されます。これは、イベントを再度添付する前に、ある種のフラグとして機能します。これがアイデアの例です。

// initial load
var attached = false;

// this will only execute code once
doSomething = function()
{
 if (!attached)
 {
  attached = true;
  //code
 }
} 

//attach your function with change event
window.onload = function()
{
 var txtbox = document.getElementById('textboxID');

 if (window.addEventListener)
 {
  txtbox.addEventListener('change', doSomething, false);
 }
 else if(window.attachEvent)
 {
  txtbox.attachEvent('onchange', doSomething);
 }
}
于 2013-01-16T18:10:37.327 に答える
5

たとえば、Chrome インスペクターを使用して、EventListener が存在するかどうかをいつでも手動で確認できます。[要素] タブには、従来の [スタイル] サブタブがあり、その近くに別の [イベント リスナー] サブタブがあります。これにより、リンクされた要素を持つすべての EventListeners のリストが得られます。

于 2016-05-12T15:12:25.193 に答える
1

イベントが添付されているかどうかを確認しようとして、これを見つけました....

もしあなたがそうするなら :

item.onclick

「null」を返します

しかし、もしそうなら:

item.hasOwnProperty('onclick')

それなら「真」です

したがって、「addEventListener」を使用してイベントハンドラーを追加する場合、それにアクセスする唯一の方法は「hasOwnProperty」を使用することだと思います。理由や方法を知りたいのですが、残念ながら、調査した後、説明が見つかりませんでした.

于 2015-04-29T16:13:31.767 に答える
1
var listenerPaste = pasteAreaElm.hasOwnProperty('listenerPaste');
if (!listenerPaste) {
    pasteAreaElm.addEventListener("paste", onPasteEvent, false);
    pasteAreaElm.listenerPaste = true;
}
于 2021-07-21T16:37:24.930 に答える
1

ページ上のどの要素がクリックに反応したかを判断するために必要な Chrome 拡張機能を作成しました。これが私がそれをした方法です:

(1) manifest.json で、「run_at」属性を「document_start」に設定します。(ページの実行を開始する前にスクリプトを挿入する必要があります。)

(2) コンテンツ スクリプトに小さなコードを追加して、スクリプトをページに挿入します。このスクリプトは、EventTarget.prototype.addEventListener をオーバーライドして、動的に割り当てられたクリック リスナーであるすべての要素にフラグを立てます。

let flagClickHandledElements = function() {
    let oldEventListener = EventTarget.prototype.addEventListener;
    EventTarget.prototype.addEventListener = function(event_name, handler_func) {
        if (event_name === 'click') {
            if (this.setAttribute) {
                this.setAttribute('data-has_click_handler', true);
            }
        }
        if (oldEventListener)
            oldEventListener(event_name, handler_func);
    }
}

function injectScript(func) {
    let codeString = '(' + func + ')();';
    let script = document.createElement('script');
    script.textContent = codeString;
    (document.head||document.documentElement).appendChild(script);
}

injectScript(flagClickHandledElements);

(3) manifest.json の "permissions" リストに "webNavigation" を追加します。

(4) バックグラウンド スクリプトにコードを追加して、ページの読み込みが完了したときにコンテンツ スクリプトに通知します。

function onPageDoneLoading(details)
{
    chrome.tabs.sendMessage(details.tabId, {"action": "doneloading"});
}

chrome.webNavigation.onCompleted.addListener(onPageDoneLoading);

(5) ページの読み込みが終了したら、コンテンツ スクリプトで、ページ上のすべての要素をスキャンして古いスタイルの「onclick」ハンドラをスキャンする別のスクリプトをページに挿入します。

let gatherOldStyleClickHandledElements = function() {
    let all_elements = document.getElementsByTagName("*");
    for (let i = 0; i < all_elements.length; i++) {
        let el = all_elements[i];
        if (el.setAttribute && el.onclick) {
            el.setAttribute('data-has_click_handler', true);
        }
    }
}

function onReceiveMessage(request) {
    if (request.action === 'doneloading') {
        injectScript(gatherOldStyleClickHandledElements);
    } else {
        console.log('Unrecognized message');
    }

    return Promise.resolve("Dummy response to keep the console quiet");
}

(6) 最後に、コンテンツ スクリプト内の要素をテストして、次のようなクリック ハンドラがあるかどうかを確認できます。

if (el.getAttribute('data-has_click_handler'))
    console.log('yep, this element has a click handler');
于 2021-04-15T21:16:35.530 に答える
0

これを実現できるスクリプトを作成しました。2 つのグローバル関数が提供されます:hasEvent(Node elm, String event)getEvents(Node elm)を利用できます。EventTargetこれはプロトタイプ メソッドadd/RemoveEventListenerを変更することに注意してください。elm.on_event = ...

詳細については GitHub をご覧ください

ライブデモ

脚本:

var hasEvent,getEvents;!function(){function b(a,b,c){c?a.dataset.events+=","+b:a.dataset.events=a.dataset.events.replace(new RegExp(b),"")}function c(a,c){var d=EventTarget.prototype[a+"EventListener"];return function(a,e,f,g,h){this.dataset.events||(this.dataset.events="");var i=hasEvent(this,a);return c&&i||!c&&!i?(h&&h(),!1):(d.call(this,a,e,f),b(this,a,c),g&&g(),!0)}}hasEvent=function(a,b){var c=a.dataset.events;return c?new RegExp(b).test(c):!1},getEvents=function(a){return a.dataset.events.replace(/(^,+)|(,+$)/g,"").split(",").filter(function(a){return""!==a})},EventTarget.prototype.addEventListener=c("add",!0),EventTarget.prototype.removeEventListener=c("remove",!1)}();
于 2015-06-10T10:33:53.943 に答える
0

2022 年更新:

この回答に基づいてイベントをアタッチおよびデタッチするために TypeScript でユーティリティ メソッドを作成しましたが、修正されました。誰かが役に立てば幸いです。

export const attachEvent = (
  element: Element,
  eventName: string,
  callback: () => void
) => {
  if (element && eventName && element.getAttribute('listener') !== 'true') {
    element.setAttribute('listener', 'true');
    element.addEventListener(eventName, () => {
      callback();
    });
  }
};

export const detachEvent = (
  element: Element,
  eventName: string,
  callback: () => void
) => {
  if (eventName && element) {
    element.removeEventListener(eventName, callback);
  }
};

インポートして、このような場所で使用します

  attachEvent(domElement, 'click', this.myfunction.bind(this));
  detachEvent(domElement, 'click', this.myfunction);
于 2022-02-24T05:46:49.193 に答える