我想要等到准备好之后再触发事件,例如:
$('.button').live('click', function(e){
e.preventDefault();
// do lots of stuff
e.run() //this proceeds with the normal event
}
是否有与上述描述的 run()
函数相等的函数?
我想要等到准备好之后再触发事件,例如:
$('.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
支持的奖励级别的极简jQuery插件:
(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));
用法:
$('.button').onButFirst('click',
function(){
console.log('doing lots of work!');
},
function(){
console.log('done lots of work!');
});
lots_of_stuff_already_done = true;
标志了 - 否则函数就无法继续递归。 - vzwickselector
匹配多个元素,则闭包将为每个元素重复使用isDone
。 - Top-Master被接受答案的更近期版本。
简要版本:
$('#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 */
}
});
这种情况下使用这样的东西的一个好例子是,当您可能有一些旧的表单代码,它能够正常工作,但是您被要求在提交表单之前添加类似于电子邮件地址验证的内容以增强表单。您可以编写一个API,然后更新前端代码,让它首先调用该API,然后再允许表单进行传统的POST提交,而无需深入挖掘后端表单POST代码。
为了实现这一点,您可以实现类似我在这里编写的代码:
$('#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);
}
个人认为,这是重新触发事件并将完全相同的数据推回的最完整方法。
e
未定义。应该是 evt.preventDefault()
。我尝试进行编辑,但我的编辑必须大于6个字符,而我只添加了2个 :( - kevnkevent.isPropagationStopped = function(){ return false; };
也可以停止事件传播。我还向事件添加了一个自定义属性,以便在处理程序中检测是否已经执行了防止操作的检查,这样就不会再执行一次了。太棒了! - Kaddath更近期的答案巧妙地使用了jQuery.one()
$('form').one('submit', function(e) {
e.preventDefault();
// do your things ...
// and when you done:
$(this).submit();
});
可以使用event
的currentTarget
。示例展示了如何提交表单。同样地,你可以从onclick
属性中获取函数等。
$('form').on('submit', function(event) {
event.preventDefault();
// code
event.currentTarget.submit();
});
不要执行e.preventDefault();
, 或者有条件地执行。
你当然不能改变原始事件的触发时间。
如果你想在稍后的某个时刻(比如 AJAX 请求的回调函数中)"重新创建"原始的 UI 事件,那么你只能用其他方式来模拟它(就像 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
});
window.setTimeout(function() {
// do your thing
}, 0);
您可以使用计时器或不使用计时器。
const form = document.querySelector('#form');
form.addEventListener('submit', (x) => {
x.preventDefault()
// Ajax or nay Code
setTimeout(() => {
x.target.submit();
}, 1000)
})