San*_*der 34 javascript jquery events javascript-events
我们正在开发一个包含旧代码的JavaScript工具,因此我们无法重写整个工具.
现在,添加了一个固定在底部的菜单,客户非常希望有一个切换按钮来打开和关闭菜单,除非关闭需要在用户开始执行菜单时自动执行,例如,当用户返回页面,并在表单字段上选择某些内容或单击时.
这可以在技术上处理一个click
事件body
,触发任何点击,但旧代码中有许多项目,其中一个点击事件在内部链接上处理,return false
并被添加到点击功能,以便网站不继续链接的href
标签.
很明显,像这样的通用函数确实有效,但是当点击内部链接时,返回false会停止传播.
$('body').click(function(){
console.log('clicked');
});
Run Code Online (Sandbox Code Playgroud)
有没有办法我可以强制进行身体点击事件,还是有另一种方法可以让菜单消失,使用一些全局点击事件或类似的东西?
无需重写多年前创建的应用程序中的所有其他点击.这将是一个怪物任务,特别是因为我不知道如何重写它们,没有返回错误,但仍然不让他们去他们的href
.
And*_*y E 61
现代DOM实现中的事件有两个阶段,捕获和冒泡.捕获阶段是第一阶段,从defaultView
文档流向事件目标,然后是冒泡阶段,从事件目标流回到事件目标defaultView
.有关更多信息,请参见http://www.w3.org/TR/DOM-Level-3-Events/#event-flow.
要处理事件的捕获阶段,你需要设置第三个参数进行addEventListener
到true
:
document.body.addEventListener('click', fn, true);
Run Code Online (Sandbox Code Playgroud)
遗憾的是,正如Wesley所说,在旧版浏览器中,事件的捕获阶段无法可靠处理,或根本无法处理.
一种可能的解决方案是处理mouseup
事件,因为点击的事件顺序是:
如果你可以确定没有处理程序取消该mouseup
事件,那么这是一种方式(而且,可以说是一种更好的方法).另一件需要注意的事情是,鼠标按下时,许多(如果不是全部)UI菜单都会消失.
this
是关键(相对于 evt.target)。参见示例。
document.body.addEventListener("click", function (evt) {
console.dir(this);
//note evt.target can be a nested element, not the body element, resulting in misfires
console.log(evt.target);
alert("body clicked");
});
Run Code Online (Sandbox Code Playgroud)
<h4>This is a heading.</h4>
<p>this is a paragraph.</p>
Run Code Online (Sandbox Code Playgroud)
与安迪·E合作,这是部队的黑暗面:
var _old = jQuery.Event.prototype.stopPropagation;
jQuery.Event.prototype.stopPropagation = function() {
this.target.nodeName !== 'SPAN' && _old.apply( this, arguments );
};
Run Code Online (Sandbox Code Playgroud)
示例:http://jsfiddle.net/M4teA/2/
请记住,如果所有事件都是通过jQuery绑定的,那么您可以在这里处理这些情况.在这个例子中,.stopPropagation()
如果我们不处理a ,我们只需调用原始文件<span>
.
你不能阻止预防,没有.
您可以做的是,在代码中手动重写这些事件处理程序.这是一个棘手的业务,但如果您知道如何访问存储的处理程序方法,您可以解决它.我玩了一下,这是我的结果:
$( document.body ).click(function() {
alert('Hi I am bound to the body!');
});
$( '#bar' ).click(function(e) {
alert('I am the span and I do prevent propagation');
e.stopPropagation();
});
$( '#yay' ).click(function() {
$('span').each(function(i, elem) {
var events = jQuery._data(elem).events,
oldHandler = [ ],
$elem = $( elem );
if( 'click' in events ) {
[].forEach.call( events.click, function( click ) {
oldHandler.push( click.handler );
});
$elem.off( 'click' );
}
if( oldHandler.length ) {
oldHandler.forEach(function( handler ) {
$elem.bind( 'click', (function( h ) {
return function() {
h.apply( this, [{stopPropagation: $.noop}] );
};
}( handler )));
});
}
});
this.disabled = 1;
return false;
});
Run Code Online (Sandbox Code Playgroud)
注意,上面的代码只适用于jQuery 1.7.如果这些点击事件与早期的jQuery版本或"内联"绑定,您仍然可以使用代码,但您需要以不同方式访问"旧处理程序".
我知道我在这里假设了很多"完美的世界"场景,例如,这些句柄显式调用.stopPropagation()
而不是返回false
.所以它仍然可能是一个无用的学术范例,但我觉得它出来了:-)
编辑:嘿,return false;
工作得很好,事件对象以相同的方式访问.