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

时间:2011-09-30 13:12:40

标签: jquery javascript-events

我想举办一个活动,直到我准备解雇它,例如

$('.button').live('click', function(e){

   e.preventDefault(); 

   // do lots of stuff

   e.run() //this proceeds with the normal event    

}

是否有与上述run()功能等效的内容?

15 个答案:

答案 0 :(得分:136)

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

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

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 ($.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!');
    });

答案 1 :(得分:66)

接受答案的最新版本。

简要版本:

$('#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,然后在允许表单执行传统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();

    }

});

答案 2 :(得分:18)

您可以执行类似

的操作
$(this).unbind('click').click();

答案 3 :(得分:10)

覆盖属性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);
}

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

答案 4 :(得分:8)

可以使用currentTarget的{​​{1}}。 示例显示了如何继续表单提交。同样,您可以从event属性等获取函数。

onclick

答案 5 :(得分:6)

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

当发生原始事件时,您当然无法改变

如果你想在一段时间之后“重新创建”原始UI事件(比如,在AJAX请求的回调中),那么你只需要以其他方式伪造它(比如在vzwick的答案中)......虽然我怀疑这种方法的可用性。

答案 6 :(得分:3)

只要“很多东西”没有做异步,这绝对是不必要的 - 事件会按顺序调用每个处理程序,所以如果在父元素上有一个onklick事件,那么这将会触发孩子的onclik事件已完全处理。 javascript不会在这里做某种“多线程”,这使得“停止”事件处理是必要的。结论:“暂停”一个事件只是为了在同一个处理程序中恢复它没有任何意义。

如果“很多东西”异步的东西,这也没有意义,因为它阻止了异步的东西做他们应该做的事情(异步的东西)并让他们像所有的东西一样序列(我们回到第一段)

答案 7 :(得分:3)

我使用的方法是:

$('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
});

答案 8 :(得分:2)

如果您正在使用锚标记,则接受的解决方案将无效。在这种情况下,您无法在致电e.preventDefault()后再次点击该链接。这是因为jQuery生成的click事件只是在本机浏览器事件之上。因此,触发“点击”锚标记上的事件不会跟随链接。相反,您可以使用像jquery-simulate这样的库来启动本机浏览器事件。

有关此内容的更多详细信息,请参阅此link

答案 9 :(得分:2)

最近的答案巧妙地使用了jQuery.one()

$('form').one('submit', function(e) {
    e.preventDefault();
    // do your things ...

    // and when you done:
    $(this).submit();
});

https://stackoverflow.com/a/41440902/510905

答案 10 :(得分:1)

另一种解决方案是在事件监听器中使用window.setTimeout ,并在事件处理完成后执行代码。有点像...

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

我使用 0 这段时间,因为我不在乎等待。

答案 11 :(得分:1)

我知道这个话题很老但我想我可以做出贡献。如果您已经知道该行为,则可以随时在处理函数中触发特定元素上的事件的默认行为。例如,当您在重置按钮上触发单击事件时,实际上会将最近的表单上的重置函数作为默认行为进行调用。在处理函数中,在使用preventDefault函数之后,您可以通过调用处理程序代码中任何位置的最近表单上的重置函数来调用默认行为。

答案 12 :(得分:0)

如果此示例可以帮助您,请在某些链接上添加“自定义确认弹出窗口”(我保留了代码“ $ .ui.Modal.confirm”,这只是执行原始操作的回调的一个示例):< / p>

//Register "custom confirm popin" on click on specific links
$(document).on(
    "click", 
    "A.confirm", 
    function(event){
        //prevent default click action
        event.preventDefault();
        //show "custom confirm popin"
        $.ui.Modal.confirm(
            //popin text
            "Do you confirm ?", 
            //action on click 'ok'
            function() {
                //Unregister handler (prevent loop)
                $(document).off("click", "A.confirm");
                //Do default click action
                $(event.target)[0].click();
            }
        );
    }
);

答案 13 :(得分:0)

如果您向表单添加事件侦听器并等待其提交,那么在检查完您需要检查的内容后,您可以使用 .submit 调用表单的提交,即

const checkoutForm = document.getElementById('checkout-form');
const cart = {};
if (checkoutForm) {
    checkoutForm.addEventListener('submit', e => {
        e.preventDefault();
        if(JSON.stringify(cart) === '{}'){
            console.log('YOUR CART IS EMPTY')
            alert('YOUR CART IS EMPTY');
            return;
        }
        else{
            checkoutForm.submit();
        }
    })
}
<form id="checkout-form" action="action-page" method="post">
  <input type="text" name="name" />
  <button>Submit</button>
</form>

这样您就可以解决表单提交问题,例如检查密码的强度和检查所有需要的字段是否都有正确的数据

答案 14 :(得分:0)

这是我使用 preventDefault 并在内部触发“点击”的旧想法。我只是将参数“阻止”传递给函数:

$(document).on('click', '.attachments_all', function(e, prevent = true){

    if(prevent){

        e.preventDefault();

        var button = $(this);
        var id = button.data('id');
    
        $.ajax({
            type: 'POST',
            url: window.location.protocol + '//' + window.location.host + path + '/attachments/attachments-in-order/' + id, 
            dataType: 'json',
            success: function(data){
                if(data.success && data.attachments){ 
                    button.trigger('click', false);
                } else {
                    swal({
                        title: "Brak załączników!",
                        text: "To zamówienie nie posiada żadnych załączników!",
                        type: "error"
                    });
                    return;
                }
            }
        });
    }

});

我希望有人会觉得它有用