一尘不染

调试时或从JavaScript代码中如何在DOM节点上查找事件侦听器?

javascript

我有一个页面,其中一些事件侦听器附加到输入框和选择框。有没有一种方法可以找出哪些事件侦听器正在观察特定的DOM节点以及什么事件?

使用以下事件附加事件:

  1. Prototype的Event.observe ;
  2. DOM的addEventListener
  3. 作为元素属性element.onclick

阅读 373

收藏
2020-04-23

共2个答案

一尘不染

如果只需要检查页面上发生的情况,则可以尝试使用VisualEvent书签。

介绍

Visual Event是一个开源Javascript书签,提供有关已附加到DOM元素的事件的调试信息。视觉事件显示:

  • 哪些元素附有事件
  • 元素附带的事件类型
  • 触发将与事件一起运行的代码
  • 定义附加功能的源文件和行号(仅Webkit浏览器和Opera)

除了可用于调试自己的代码外,Visual Event还可以用作教育工具,显示已创作了多少个网站。

Visual Event是开源软件(GPLv2),Git存储库托管在GitHub上,供你分叉和修改!

安装

由于Visual Event是一个书签,因此在任何网页上安装和运行它都非常简单:

  • 将右侧的“可视事件”链接拖到书签栏:可视事件
  • 加载使用支持的Javascript库之一的网页
  • 点击书签栏中的“视觉事件”
  • 查看附加在文档元素上的事件处理程序。

视觉事件的演示,它会自动加载是可用。本演示使用DataTables创建一个测试页面,其中将许多事件附加到不同的元素上。

这个怎么运作
事实证明,W3C推荐的DOM接口没有提供任何标准方法来查找将哪些事件侦听器附加到特定元素。尽管这似乎是一个疏忽,但有人提议将一个名为eventListenerList的属性包含在3级DOM规范中,但不幸的是在以后的草案中被删除了。因此,我们不得不查看各个Javascript库,这些Java库通常维护附加事件的缓存(以便以后可以将其删除并执行其他有用的抽象)。

这样,为了使Visual Event显示事件,它必须能够从Javascript库中解析事件信息。当前,Visual Event支持以下库:

DOM 0 events
jQuery 1.2+
YUI 2
MooTools 1.2+
Prototype 1.6+
Glow
ExtJS 4.0.x

如何参与
Visual Event是开源软件,可在GPL v2许可下获得。源代码控制使用Git完成,该项目在GitHub上有一个页面。确实非常欢迎对Visual Event的任何改进和建议!如果遇到特定问题,请在GitHub上针对你遇到的问题打开一个问题,包括指向该问题发生页面的链接。还非常鼓励叉和拉请求!

你可能感兴趣的一个领域是如何添加对其他Javascript库的支持。所需的关键是访问库使用的事件缓存,因为没有它,就无法确定哪些节点具有事件和附加的代码。

VisualEvent类有一个称为VisualEvent.parsers的静态数组,它是一个函数数组-要添加新的解析器,只需将函数推送到该数组即可。该函数必须返回带有以下参数的Javascript对象数组:

[
    {
        "node": {element},            // The DOM element that has attached events
        "listeners": [                // Array of attached events
            {
                "type": {string},     // The event type - click, change, keyup etc
                "func": {string},     // The code that will handle the event, from Function.toString()
                "removed": {boolean}, // If the event has been removed or not (typically will be false, but used if the library doesn't remove the event from its cache)
                "source": {string}    // Library name and version that attached the event (e.g. "jQuery 1.7")
            },
            ...
        ]
    },
    ...
]

建立视觉事件
为了运行Visual Event的本地副本,你必须构建它,因为此过程会进行文件串联,这会将库解析器引入主文件。构建过程还将构建JSDoc文档并压缩Javascript文件(除非使用调试完成)。

要构建Visual Event,你需要的是一个将运行bash脚本并在终端中输入命令./build.sh debug的系统。这将在“ builds”目录中使用正确的加载器和build Visual Event目录创建一个新目录(请注意,在开发过程中和部署时,时间戳用于帮助防止小书签的缓存问题)。以下是构建脚本的用法:

Visual Event build script - usage:
  ./build.sh [loader-dir] [debug]
    loader-dir - The web-address of the build files. Note that the build
      directory name is automatically appended. For example:
        localhost/VisualEvent/builds - default if no option is provided
        sprymedia.co.uk/VisualEvent/builds
    debug - Debug indicator. Will not compress the Javascript

  Example deploy build:
    ./build.sh sprymedia.co.uk/VisualEvent/builds

  Example debug build:
    ./build.sh localhost/VisualEvent/builds debug

提供的文件bookmarklet.html可以轻松轻松地构建自己的书签加载器。通常,你只需要修改小书签的路径。该链接在每次按键时都会更新,你可以像使用其他任何书签一样安装它

2020-04-23
一尘不染

这取决于事件的附加方式。为了便于说明,我们具有以下单击处理程序:

var handler = function() { alert('clicked!') };

我们将使用不同的方法将其附加到元素上,其中一些方法允许检查,而另一些则不允许。

方法A)单事件处理程序

element.onclick = handler;
// inspect
alert(element.onclick); // alerts "function() { alert('clicked!') }"

方法B)多个事件处理程序

if(element.addEventListener) { // DOM standard
    element.addEventListener('click', handler, false)
} else if(element.attachEvent) { // IE
    element.attachEvent('onclick', handler)
}
// cannot inspect element to find handlers

方法C):jQuery

$(element).click(handler);

1.3.x

// inspect
var clickEvents = $(element).data("events").click;
jQuery.each(clickEvents, function(key, value) {
    alert(value) // alerts "function() { alert('clicked!') }"
})

1.4.x(将处理程序存储在对象中)

// inspect
var clickEvents = $(element).data("events").click;
jQuery.each(clickEvents, function(key, handlerObj) {
    alert(handlerObj.handler) // alerts "function() { alert('clicked!') }"
    // also available: handlerObj.type, handlerObj.namespace
})

(请参阅jQuery.fn.data和jQuery.data)

方法D):原型(messy)

$(element).observe('click', handler);

1.5.x

// inspect
Event.observers.each(function(item) {
    if(item[0] == element) {
        alert(item[2]) // alerts "function() { alert('clicked!') }"
    }
})

  • 1.6 to 1.6.0.3, inclusive (got very difficult here)
// inspect. "_eventId" is for < 1.6.0.3 while 
// "_prototypeEventID" was introduced in 1.6.0.3
var clickEvents = Event.cache[element._eventId || (element._prototypeEventID || [])[0]].click;
clickEvents.each(function(wrapper){
    alert(wrapper.handler) // alerts "function() { alert('clicked!') }"
})
  • 1.6.1 (little better)
// inspect
var clickEvents = element.getStorage().get('prototype_event_registry').get('click');
clickEvents.each(function(wrapper){
    alert(wrapper.handler) // alerts "function() { alert('clicked!') }"
})
2020-04-23