如何使用event.preventDefault()后触发事件

我想举办一个活动,直到我准备开火为止

$('.button').live('click', function(e){ e.preventDefault(); // do lots of stuff e.run() //this proceeds with the normal event } 

有没有一个相当于上面描述的run()函数?

不。 一旦事件被取消,它被取消。

您可以稍后重新启动事件,使用标志来确定您的自定义代码是否已经运行 – 例如(请忽略公然的命名空间污染):

 var lots_of_stuff_already_done = false; $('.button').on('click', function(e) { if (lots_of_stuff_already_done) { lots_of_stuff_already_done = false; // reset flag return; // let the event bubble away } e.preventDefault(); // do lots of stuff lots_of_stuff_already_done = true; // set flag $(this).trigger('click'); }); 

更广义的变体(避免全局命名空间污染的附加好处)可能是:

 function onWithPrecondition(callback) { var isDone = false; return function(e) { if (isDone === true) { isDone = false; return; } e.preventDefault(); callback.apply(this, arguments); isDone = true; $(this).trigger(e.type); } } 

用法:

 var someThingsThatNeedToBeDoneFirst = function() { /* ... */ } // do whatever you need $('.button').on('click', onWithPrecondition(someThingsThatNeedToBeDoneFirst)); 

Promise支持的Bonus超简约jQuery插件:

 (function( $ ) { $.fn.onButFirst = function(eventName, /* the name of the event to bind to, eg 'click' */ workToBeDoneFirst, /* callback that must complete before the event is re-fired */ workDoneCallback /* optional callback to execute before the event is left to bubble away */) { var isDone = false; this.on(eventName, function(e) { if (isDone === true) { isDone = false; workDoneCallback && workDoneCallback.apply(this, arguments); return; } e.preventDefault(); // capture target to re-fire event at var $target = $(this); // set up callback for when workToBeDoneFirst has completed var successfullyCompleted = function() { isDone = true; $target.trigger(e.type); }; // execute workToBeDoneFirst callback var workResult = workToBeDoneFirst.apply(this, arguments); // check if workToBeDoneFirst returned a promise if ($.isFunction(workResult.then)) { workResult.then(successfullyCompleted); } else { successfullyCompleted(); } }); return this; }; }(jQuery)); 

用法:

 $('.button').onButFirst('click', function(){ console.log('doing lots of work!'); }, function(){ console.log('done lots of work!'); }); 

接受答案的更新版本。

简短版本:

 $('#form').on('submit', function(e, options) { options = options || {}; if ( !options.lots_of_stuff_done ) { e.preventDefault(); $.ajax({ /* do lots of stuff */ }).then(function() { // retrigger the submit event with lots_of_stuff_done set to true $(e.currentTarget).trigger('submit', { 'lots_of_stuff_done': true }); }); } else { /* allow default behavior to happen */ } }); 


一个好的用例就是这样的地方,你可能有一些遗留的表单代码可以工作,但是在提交表单之前,你已经被要求增加一些类似电子邮件地址validation的function。 您可以编写一个API,然后更新您的前端代码,以便在允许表单执行传统POST之前先打这个API,而不是通过后端表单后代码进行挖掘。

要做到这一点,你可以实现类似于我在这里写的代码:

 $('#signup_form').on('submit', function(e, options) { options = options || {}; if ( !options.email_check_complete ) { e.preventDefault(); // Prevent form from submitting. $.ajax({ url: '/api/check_email' type: 'get', contentType: 'application/json', data: { 'email_address': $('email').val() } }) .then(function() { // e.type === 'submit', if you want this to be more dynamic $(e.currentTarget).trigger(e.type, { 'email_check_complete': true }); }) .fail(function() { alert('Email address is not valid. Please fix and try again.'); }) } else { /** Do traditional <form> post. This code will be hit on the second pass through this handler because the 'email_check_complete' option was passed in with the event. */ $('#notifications').html('Saving your personal settings...').fadeIn(); } }); 

你可以做类似的事情

 $(this).unbind('click').click(); 

覆盖属性isDefaultPrevented像这样防止:

 $('a').click(function(evt){ evt.preventDefault(); // in async handler (ajax/timer) do these actions: setTimeout(function(){ // override prevented flag to prevent jquery from discarding event evt.isDefaultPrevented = function(){ return false; } // retrigger with the exactly same event data $(this).trigger(evt); }, 1000); } 

恕我直言,这是完全相同的数据重新触发事件的最完整的方式。

可以使用event currentTarget 。 示例显示如何进行表单提交。 同样,你可以从onclick属性等获得function

 $('form').on('submit', function(event) { event.preventDefault(); // code event.currentTarget.submit(); }); 

只是不要执行e.preventDefault(); ,或者有条件地执行。

原始的事件动作发生 ,你当然不能改变。

如果你想在一段时间之后“重新创build”原始的UI事件(比如,在AJAX请求的callback中),那么你只需要用其他方式来伪造它(就像在vzwick的答案中一样)质疑这种方法的可用性。

我使用的方法是这样的:

 $('a').on('click', function(event){ if (yourCondition === true) { //Put here the condition you want event.preventDefault(); // Here triggering stops // Here you can put code relevant when event stops; return; } // Here your event works as expected and continue triggering // Here you can put code you want before triggering }); 

只要“很多东西”没有进行asynchronous操作,这绝对是不必要的 – 事件会按顺序调用每个处理程序,所以如果父元素上的onklick事件会在onclik-孩子的事件已经完全处理了。 javascript在这里并没有做一些“multithreading”,使得“停止”事件处理成为必需。 结论:“暂停”一个事件只是为了恢复它在同一个处理程序没有任何意义。

如果“很多东西” asynchronous的,这也是没有意义的,因为它阻止asynchronous的事情做他们应该做的事(asynchronous的东西),让他们像一切顺序(我们回到我的第一段)

另一个解决scheme是在事件监听器中使用window.setTimeout 并在事件过程结束后执行代码。 就像是…

 window.setTimeout(function() { // do your thing }, 0); 

因为我不在乎等待,所以我用了0

如果您正在使用锚标签,接受的解决scheme将无法正常工作。 在这种情况下,您将无法在调用e.preventDefault()之后再次单击该链接。 那是因为jQuery生成的点击事件只是在本地浏览器事件的顶层。 所以触发一个锚点标签上的“点击”事件不会跟随链接。 相反,你可以使用像jquery-simulate这样的库,它可以让你启动本地浏览器事件。

关于这方面的更多细节可以在这个链接中find