jQuery 使用 event.preventDefault() 后如何触发事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7610871/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to trigger an event after using event.preventDefault()
提问by Mazatec
I want to hold an event until I am ready to fire it e.g
我想举办一个活动,直到我准备好触发它,例如
$('.button').live('click', function(e){
e.preventDefault();
// do lots of stuff
e.run() //this proceeds with the normal event
}
Is there an equivalent to the run()
function described above?
是否有与上述run()
功能等效的功能?
回答by vzwick
Nope. Once the event has been canceled, it is canceled.
不。一旦事件被取消,它就会被取消。
You can re-fire the event later on though, using a flag to determine whether your custom code has already run or not - such as this (please ignore the blatant namespace pollution):
不过,您可以稍后重新触发该事件,使用标志来确定您的自定义代码是否已经运行——例如(请忽略公然的命名空间污染):
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');
});
A more generalized variant (with the added benefit of avoiding the global namespace pollution) could be:
一个更通用的变体(具有避免全局命名空间污染的额外好处)可能是:
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);
}
}
Usage:
用法:
var someThingsThatNeedToBeDoneFirst = function() { /* ... */ } // do whatever you need
$('.button').on('click', onWithPrecondition(someThingsThatNeedToBeDoneFirst));
Bonus super-minimalistic jQuery plugin with Promise
support:
额外支持的超简约 jQuery 插件Promise
:
(function( $ ) {
$.fn.onButFirst = function(eventName, /* the name of the event to bind to, e.g. '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 (workResult && $.isFunction(workResult.then))
{
workResult.then(successfullyCompleted);
}
else
{
successfullyCompleted();
}
});
return this;
};
}(jQuery));
Usage:
用法:
$('.button').onButFirst('click',
function(){
console.log('doing lots of work!');
},
function(){
console.log('done lots of work!');
});
回答by Cory Danielson
A more recent version of the accepted answer.
已接受答案的更新版本。
Brief version:
简要版本:
$('#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 */
}
});
A good use case for something like this is where you may have some legacy form code that works, but you've been asked to enhance the form by adding something like email address validation before submitting the form. Instead of digging through the back-end form post code, you could write an API and then update your front-end code to hit that API first before allowing the form to do it's traditional POST.
像这样的一个很好的用例是您可能有一些有效的遗留表单代码,但是您被要求通过在提交表单之前添加电子邮件地址验证之类的东西来增强表单。您可以编写一个 API,然后更新您的前端代码以在允许表单执行传统的 POST 之前首先命中该 API,而不是挖掘后端表单发布代码。
To do that, you can implement code similar to what I've written here:
为此,您可以实现类似于我在此处编写的代码:
$('#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();
}
});
回答by Rafael Oliveira
You can do something like
你可以做类似的事情
$(this).unbind('click').click();
回答by Tomislav Simi?
Override the property isDefaultPrevented
like this:
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);
}
IMHO, this is most complete way of retriggering the event with the exactly same data.
恕我直言,这是使用完全相同的数据重新触发事件的最完整方式。
回答by Salvis Blūzma
It is possible to use currentTarget
of the event
.
Example shows how to proceed with form submit. Likewise you could get function from onclick
attribute etc.
它是可以使用currentTarget
的event
。示例显示了如何进行表单提交。同样,您可以从onclick
属性等获取功能。
$('form').on('submit', function(event) {
event.preventDefault();
// code
event.currentTarget.submit();
});
回答by Lightness Races in Orbit
Just don't perform e.preventDefault();
, or perform it conditionally.
只是不要执行e.preventDefault();
,或有条件地执行。
You certainly can't alter whenthe original event action occurs.
你当然无法改变时,原来的事件动作发生。
If you want to "recreate" the original UI event some time later (say, in the callback for an AJAX request) then you'll just have to fake it some other way (like in vzwick's answer)... though I'd question the usability of such an approach.
如果您想在一段时间后“重新创建”原始 UI 事件(例如,在 AJAX 请求的回调中),那么您只需要以其他方式伪造它(例如在 vzwick 的回答中)...尽管我会质疑这种方法的可用性。
回答by Oranges13
A more recent answer skillfully uses jQuery.one()
最近的一个答案巧妙地使用了 jQuery.one()
$('form').one('submit', function(e) {
e.preventDefault();
// do your things ...
// and when you done:
$(this).submit();
});
回答by Hokusai
The approach I use is this:
我使用的方法是这样的:
$('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
});
回答by oezi
as long as "lots of stuff" isn't doing something asynchronous this is absolutely unneccessary - the event will call every handler on his way in sequence, so if theres a onklick-event on a parent-element this will fire after the onclik-event of the child has processed completely. javascript doesn't do some kind of "multithreading" here that makes "stopping" the event processing neccessary. conclusion: "pausing" an event just to resume it in the same handler doesn't make any sense.
只要“很多东西”没有做一些异步的事情,这绝对是不必要的 - 该事件将按顺序调用每个处理程序,所以如果父元素上有一个 onklick 事件,这将在 onclik 之后触发 -孩子的事件已经完全处理了。javascript 没有在这里做某种“多线程”,这使得“停止”事件处理是必要的。结论:“暂停”一个事件只是为了在同一个处理程序中恢复它没有任何意义。
if "lots of stuff" issomething asynchronous this also doesn't make sense as it prevents the asynchonous things to do what they should do (asynchonous stuff) and make them bahave like everything is in sequence (where we come back to my first paragraph)
如果“很多东西”是异步的,这也没有意义,因为它阻止异步的东西做他们应该做的事情(异步的东西)并使它们像一切都按顺序一样(我们回到我的第一段) )
回答by Miguel Carvajal
The accepted solution wont work in case you are working with an anchor tag. In this case you wont be able to click the link again after calling e.preventDefault()
. Thats because the click event generated by jQuery is just layer on top of native browser events. So triggering a 'click' event on an anchor tag wont follow the link. Instead you could use a library like jquery-simulatethat will allow you to launch native browser events.
如果您正在使用锚标记,则已接受的解决方案将不起作用。在这种情况下,您将无法在调用 后再次单击该链接e.preventDefault()
。那是因为 jQuery 生成的点击事件只是本机浏览器事件之上的一层。所以在锚标签上触发“点击”事件不会跟随链接。相反,您可以使用像jquery-simulate这样的库,它允许您启动本机浏览器事件。
More details about this can be found in this link
可以在此链接中找到有关此的更多详细信息