我一直想知道......所以你有这样的代码:
$('#click-me');
然后你附上它:
$('#click-me').click(someFunction);
“元数据”在哪里说:
“嘿”jQuery-object#click-me,“点击后我会指向'someFunction'!”
我知道事件处理程序可能会被破坏,例如我的Backbone.js情况,我的事件因为重新渲染整个页面而停止触发,一路上破坏了一些背景函数/对象/视图.. (这是为什么我问这个问题的背景)
现在,我的问题是:
事件的元数据存储在哪里?它们是如何被销毁的? 它们是否存储在将其绑定到函数的函数中?它们是否属于DOM'元数据'(如果有的话)本身?
我正在努力学习JavaScript的复杂性,因为我已经厌倦了错误。除此之外,我想知道是否应该留意可能会分离我的事件等的垃圾收集。来自C#,我会说DOM中的JavaScript真的是......
(另外,作为旁注,如何访问这些事件并'调试'它们?firefox?chrome?)
更新
用不同的词来说,将DOM元素连接到存储的某个事件的信息在哪里? DOM?对象? (或者...... jQuery是否映射它?JavaScript是否有'元数据'? 它围绕着这个背景。
答案 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。
从代码调用JQuery.events.add
开始,您可以在事件部分here下找到此信息。这是不我认为记录的add()
接下来,这段代码就是神奇的东西。因此,它会调用element.addEventListener或attachEvent。了解它如何为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 html
,empty
,remove
,replace
时,所有使用jQuery包装并且具有绑定到它们或数据集的事件的DOM节点将自动清除等。
这就是为什么永远不要使用innerHTML
或其他本机DOM方法来插入/替换之前由jQuery更改过的内容。除非您手动重置jQuery.cache对象,否则将导致泄漏您将无法清除。
还有一个未记录的方法jQuery.cleanData
,它将DOM节点的集合作为参数,并迭代它们并清除所有事件绑定,数据并从缓存中删除对这些元素的引用。如果您有从主DOM树分离的DOM片段,并且存在无法正确清理它们的风险,那么这个可能很有用。
答案 3 :(得分:0)
jQuery保留自己的元素事件处理程序映射。除非你以某种方式滥用图书馆,否则很少,很少会引起担心。