6

可能重复:
jQuery - 如何绑定 DOM 元素上的所有事件?

想象一下,如果我们想让某些元素完全不可交互。

我们当然可以为 click 事件绑定一个阻止默认值,如下所示:

$('form *').bind('click', function(event) {
    event.preventDefault();
});

但这只是一个事件,还有更多事件,例如悬停、聚焦、选择启动等等。

我们可以在一行中指定它们,例如“click focus hover dblclick blur selectstart”,但这没有多大意义,也不容易维护。

那么,是否可以在不区分事件类型的情况下绑定事件侦听器?也许一些本机 JavaScript 侦听器允许它?

4

6 回答 6

4

没有这种可能性,因为并非所有元素都支持相同的事件,并且并非所有事件都以相同的方式运行。您始终必须明确提供事件列表,无论是静态定义还是由吐出事件名称的脚本动态定义。

尽管我链接到一个创建事件名称数组的脚本,但这些仅在一个元素上创建。您当然应该使用更复杂和更慢的脚本来生成它,该脚本枚举所有有问题的元素并添加缺失的事件。使用 Javascript 对象作为关联数组,以更快地搜索是否添加了特定事件。

更好的建议

您尝试做的可能是一个高度过度设计的解决方案。当我创建一个应禁用某些元素(无论是链接、按钮或其他任何东西)的演示可点击界面时,我宁愿通过定义一个禁用相关元素的 CSS 类来做到这一点,并有一个简单的脚本在之后禁用。

您还可以通过提供您希望在特定元素上禁用哪些事件(默认为click事件)来进一步利用这一点。

<!-- no events; use defaults -->
<a href="#" class="disable">No-follow link</a>
<button class="disable">Nothing happens</button>
<!-- provide events -->
<a href="#" class="disable" data-events="click blur">No-follow link</a>
<form class="disable" data-events="submit">...</form>

脚本

$(function() {

    var disable = function(evt) {
        evt.preventDefault();
        console.log("Prevented on " + evt.target.tagName);
    };

    $(".disable").each(function() {
        var ctx = $(this);
        ctx.bind(ctx.data("events") || "click", disable);
    });
});

使用智能默认值

上例定义了一个单一的事件默认值。click事件。这很好,并且在大多数情况下都有效,但并非全部。form例如,元素总是必须定义应禁用的提交事件。所以。然后智能默认。我们还应该考虑这样一个事实,即需要抑制的事件列表通常很短。如果我们使用默认值覆盖大多数情况,我们只会对那些实际偏离默认值的元素产生很小的开销。

$(function() {

    // click is still default event
    // this object defines per element events that aren't just click
    var extraDefaults = {
        form: "submit"
    };

    var disable = function(evt) {
        evt.preventDefault();
        console.log("Prevented on " + evt.target.tagName);
    };

    $(".disable").each(function() {
        var ctx = $(this);
        ctx.bind(
            // use inline-defined events
            ctx.data("events") ||
            // use extra defaults if present
            extraDefaults[this.tagName.toLower()] ||
            // just use default click event
            "click",
            disable);
    });
});
于 2012-08-31T11:03:51.170 回答
1

您可以像这样绑定大多数 jQuery 事件:

$("#elementID").on(Object.keys(jQuery.event.fixHooks).join(" "), function(e) { 
    e.preventDefault(); 
});

这将阻止以下事件的默认值:

click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave keydown keypress keyup contextmenu

小提琴

于 2012-08-31T11:22:47.603 回答
1

好吧,在考虑了所有选项之后,对于所有这些活动的喧嚣,它看起来仍然不方便。由于它还必须单独绑定每个事件的处理程序,因此脚本也会影响性能。

我将坚持使用更简单的解决方案,只需在顶部放置一个带有透明 bg 的 div 来覆盖我们的元素。

$('form').css('position','relative').prepend($('<div class="mask" style="position:absolute;z-index:9000;height:100%;width:100%;background-image:url(1px_transparent.png);"></div>'));

这将自动填充元素的整个区域,或者,我们可以使用半透明的图片,这样用户也会理解这是锁定元素,不会引起混淆。

要解锁,我们只需从元素中删除 .mask div。

编辑

新小提琴:http: //jsfiddle.net/YAdXk/8/

实际上我们可以通过将tabindex属性设置为-1

.find('input,textarea,select').attr('tabindex','-1');

更新的小提琴也可以防止标签。

编辑2

或者,我们可以扩展 jQuery 以在任何元素上使用我们的自定义lock()和函数。unlock()

见最后一个小提琴:http: //jsfiddle.net/YAdXk/13/

(function($) {
$.fn.lock= function() {
    return this.each(function() {
        $(this).css('position','relative').prepend($('<div class="mask" style="position:absolute;z-index:9000;height:100%;width:100%;background-image:url('+transparent_picture+');"></div>')).find('input,textarea,select').attr('tabindex','-1');
    });
};   

$.fn.unlock= function() {
    return this.each(function() {
        $(this).find('*').removeAttr('tabindex').filter('.mask').remove();
   });
};

})( jQuery )
于 2012-08-31T12:12:35.130 回答
0
var all_events = "click blur focus mouse"; //etc...

$('form *').bind(all_events, function(event) {
        event.preventDefault();
});

现在更容易维护;)

于 2012-08-31T11:16:56.483 回答
0

jQuery在这里定义了所有快捷事件类型,因此您可以使用该字符串来存储所有事件以供重复使用:

var events = "blur focus focusin focusout load resize scroll unload click dblclick " +
"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
"change select submit keydown keypress keyup error contextmenu";

$('button').bind(events, function() {
    // hey
});
于 2012-08-31T11:18:40.350 回答
0

是的,有可能一次捕获一种类型的所有事件!但是您需要明确指定所有事件类型。

您的代码示例"form *"效率低下,并且不会捕获代码执行后添加的元素上的事件。

由于 javascript 事件的冒泡效应,您可以在最父元素上分配一个 catch all 事件处理程序,例如$("form")or $("body"),然后添加preventDefault()到该元素。

示例代码:

$("a").on("click", function() {
    $("body").append("<p>Clicked...</p>");
});
$("body").on("click", function(e) {
  e.preventDefault();
});

和:

<div>
    <p><a href="#" target="_blank">Click on me</a></p>
</div>​

在父元素上捕获所有事件的概念通常称为事件委托

于 2012-08-31T11:42:24.263 回答