附加事件处理程序的元数据存储在哪里?在“DOM”,对象,还是......?

时间:2012-02-03 03:10:32

标签: javascript jquery javascript-events event-handling backbone.js

我一直想知道......所以你有这样的代码:

$('#click-me');

然后你附上它:

$('#click-me').click(someFunction);

“元数据”在哪里说:

“嘿”jQuery-object#click-me,“点击后我会指向'someFunction'!”

我知道事件处理程序可能会被破坏,例如我的Backbone.js情况,我的事件因为重新渲染整个页面而停止触发,一路上破坏了一些背景函数/对象/视图.. (这是为什么我问这个问题的背景)

现在,我的问题是

事件的元数据存储在哪里?它们是如何被销毁的? 它们是否存储在将其绑定到函数的函数中?它们是否属于DOM'元数据'(如果有的话)本身?

我正在努力学习JavaScript的复杂性,因为我已经厌倦了错误。除此之外,我想知道是否应该留意可能会分离我的事件等的垃圾收集。来自C#,我会说DOM中的JavaScript真的是......

(另外,作为旁注,如何访问这些事件并'调试'它们?firefox?chrome?)


更新

用不同的词来说,将DOM元素连接到存储的某个事件的信息在哪里? DOM?对象? (或者...... jQuery是否映射它?JavaScript是否有'元数据'? 它围绕着这个背景。

4 个答案:

答案 0 :(得分:5)

更新:所以我误解了这个问题,你想知道事件是如何绑定在javascript和html的上下文中的。我在下面的原始答案描述了jquery如何创建和管理事件。归结为致电element.addEventListener

在MDN文档中,您会看到 eventtarget 可以是元素文档窗口或者的XMLHttpRequest 。从w3 specifications on DOM Events事件目标添加,删除和调度事件。因此,即使信息可能存储在封装元素之类的内容中,也会在浏览器级别实现

从你提到的关于复制然后从正文中替换html的问题中删除事件,我认为浏览器只是给你标记(没有事件元数据)然后当你替换它,元数据消失了。 (http://jsfiddle.net/qu9bF/1/


原始答案:jquery事件处理程序的工作原理。

好的,所以我开始挖掘这个,用于JQuery 1.4.2(因为我必须使用几个工具,所有这些都没有更新)

首先看看这个: http://james.padolsey.com/jquery/#v=1.4.2&fn=click

function (fn) {
    return fn ? this.bind(name, fn) : this.trigger(name);
}

这就是click 定义的,它实际上并没有在代码中定义。 JQuery为所有事件/处理函数定义了这个函数,如下所示,是的!它们是动态创建/定义

jQuery.each( ("blur focus focusin focusout load resize scroll unload click
            dblclick " +
        "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
        "change select submit keydown keypress keyup error").split(" "), 
    function( i, name ) {
        // the magic happens here..
        //each string is added as a function to the prototype
        jQuery.fn[ name ] = function( fn ) {
                return fn ? this.bind( name, fn ) : this.trigger( name );
        };//if a handler is NOT specified then attach an event OR call/trigger it

        if ( jQuery.attrFn ) {
                jQuery.attrFn[ name ] = true;
        }
});

从这里开始,我们需要查看bind,现在bind()one()也是这样定义的。搜索“代码:绑定和一个事件” here

从这里开始,我使用chrome和这个小提琴http://jsfiddle.net/qu9bF/来进入代码。来自c.each(["bind"的块是绑定函数的定义方式。源是缩小的,但是chrome can format it

enter image description here

从代码调用JQuery.events.add开始,您可以在事件部分here下找到此信息。这是我认为记录的add()

接下来,这段代码就是神奇的东西。因此,它会调用element.addEventListenerattachEvent。了解它如何为attachEvent添加 on

// Check for a special event handler
// Only use addEventListener/attachEvent if the special
// events handler returns false
if ( !special.setup || 
      special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
      // Bind the global event handler to the element
       if ( elem.addEventListener ) {
             elem.addEventListener( type, eventHandle, false );

        } else if ( elem.attachEvent ) {
             elem.attachEvent( "on" + type, eventHandle );
        }
 }

你有它! :)我希望它能回答你的两个问题。您可以链接到jquery源的非缩小版本,并逐步完成它以解决问题。 IMO有时IE9的调试器更直观(这是我唯一使用的),并使用我提到的页面来浏览源代码。

答案 1 :(得分:2)

点击或提交(不受jQuery约束)等常规事件实际上只是DOM元素本身的属性('onclick','onsubmit')。

对于jQuery事件,库在绑定它们时保留它自己的记录,并在触发它时查看它。 jQuery将有关元素的所有数据放在标准位置,您可以使用$(e).data()访问该位置。对于活动,它只是$(e).data('events')

您可以使用$().unbind()取消绑定jQuery事件,使用delete关键字取消常规事件,以删除与给定事件对应的对象属性。

答案 2 :(得分:2)

jQuery将所有事件绑定和数据缓存存储在jQuery.cache对象上。当您使用jQuery htmlemptyremovereplace时,所有使用jQuery包装并且具有绑定到它们或数据集的事件的DOM节点将自动清除等。

这就是为什么永远不要使用innerHTML或其他本机DOM方法来插入/替换之前由jQuery更改过的内容。除非您手动重置jQuery.cache对象,否则将导致泄漏您将无法清除。

还有一个未记录的方法jQuery.cleanData,它将DOM节点的集合作为参数,并迭代它们并清除所有事件绑定,数据并从缓存中删除对这些元素的引用。如果您有从主DOM树分离的DOM片段,并且存在无法正确清理它们的风险,那么这个可能很有用。

答案 3 :(得分:0)

jQuery保留自己的元素事件处理程序映射。除非你以某种方式滥用图书馆,否则很少,很少会引起担心。

相关问题