Laravel 8中如何阻止Ajax加载表单的默认提交行为?
问题背景
我在Laravel 8中开发了一款博客应用,目前正在通过jQuery(v3.5.0)AJAX实现评论回复功能。
评论表单模板(comment-form.blade.php)
<div class="form-wrapper"> <div class="alert-box-ajax alert-box alert-box--success"> Your comment is pending </div> <div class="alert-box-ajax alert-box alert-box--error"> Failed to add comment! </div> <form class="commentForm" method="post" action="{{ route('comment.submit') }}" autocomplete="off" novalidate> @csrf <fieldset> <input type="hidden" name="article_id" value="{{ isset($article->id) ? $article->id : $article_id }}"> <input type="hidden" name="parent_id" value="{{ $comment->id ?? '' }}"> <div class="message form-field"> <textarea name="msg" id="message" class="h-full-width" placeholder="Your Message" required></textarea> @error('msg') <p class="help-block text-danger">{{ $message }}</p> @enderror </div> <br> <input name="submit" id="submit" class="btn btn--primary btn-wide btn--large h-full-width" value="Add Comment" type="submit"> </fieldset> </form> </div>
该模板会为每条评论重复渲染,以便对任意评论添加回复。
AJAX提交代码
$(".commentForm").each(function () { var form = $(this); form.validate({ errorElement: "p", errorClass: "help-block text-danger", submitHandler: function (_form, event) { event.preventDefault(); var $fields = form.find("textarea"), url = form.attr("action"), data = form.serialize(); $.ajax({ dataType: "json", type: "post", url: url, data: data, cache: false, success: function (response) { if (response.status === 'success') { form.closest(".form-wrapper").find(".alert-box--success").slideDown(250).delay(2500).slideUp(250) .slideDown(250) .delay(2500) .slideUp(250); $fields.val(""); } else { form.closest(".form-wrapper").find(".alert-box--error").slideDown(250).delay(2500).slideUp(250) .slideDown(250) .delay(2500) .slideUp(250); } }, error: function (err) { console.log(err); }, }); }, }); });
问题描述
应用设置为单篇文章初始最多加载10条评论,剩余评论通过页面滚动触发Ajax加载。启用该功能后,上述脚本无法阻止通过Ajax加载的表单的默认提交行为。
注意: 问题并非提交事件本身,而是无法阻止其默认行为。
疑问
- 该问题的成因是什么?
- 最可靠的解决方案是什么?
问题成因
当前代码仅在页面初始加载时,对已存在的.commentForm元素绑定验证和提交逻辑。但通过AJAX动态加载的评论表单是在初始页面渲染后才添加到DOM中的,这些新元素没有被绑定validate方法,提交时不会触发自定义的submitHandler,因此无法阻止默认提交行为。
解决方案
推荐两种可靠方案:
方案1:事件委托+手动验证(高效简洁)
放弃对单个表单绑定validate,改用事件委托监听所有.commentForm的提交事件,手动触发验证后执行AJAX提交:
// 绑定到评论列表的父容器(需替换为实际的父容器选择器,比如#comments-list) $("#comments-list").on("submit", ".commentForm", function(event) { event.preventDefault(); var form = $(this); // 手动触发验证,不通过则终止 if (!form.valid()) return; // 执行AJAX提交逻辑 var $fields = form.find("textarea"), url = form.attr("action"), data = form.serialize(); $.ajax({ dataType: "json", type: "post", url: url, data: data, cache: false, success: function (response) { if (response.status === 'success') { form.closest(".form-wrapper").find(".alert-box--success") .slideDown(250).delay(2500).slideUp(250) .slideDown(250).delay(2500).slideUp(250); $fields.val(""); } else { form.closest(".form-wrapper").find(".alert-box--error") .slideDown(250).delay(2500).slideUp(250) .slideDown(250).delay(2500).slideUp(250); } }, error: function (err) { console.log(err); }, }); }); // 初始化所有初始表单的验证规则 $(".commentForm").validate({ errorElement: "p", errorClass: "help-block text-danger" });
无论初始还是动态加载的表单,提交事件都会被父容器捕获处理,同时保留jQuery Validate的验证能力。
方案2:动态加载后重新初始化验证
封装初始化逻辑为函数,在页面加载和动态加载评论完成后都调用:
// 封装初始化函数,标记已初始化避免重复绑定 function initCommentForms() { $(".commentForm").not(".initialized").each(function () { var form = $(this); form.addClass("initialized"); form.validate({ errorElement: "p", errorClass: "help-block text-danger", submitHandler: function (_form, event) { event.preventDefault(); var $fields = form.find("textarea"), url = form.attr("action"), data = form.serialize(); $.ajax({ dataType: "json", type: "post", url: url, data: data, cache: false, success: function (response) { if (response.status === 'success') { form.closest(".form-wrapper").find(".alert-box--success") .slideDown(250).delay(2500).slideUp(250) .slideDown(250).delay(2500).slideUp(250); $fields.val(""); } else { form.closest(".form-wrapper").find(".alert-box--error") .slideDown(250).delay(2500).slideUp(250) .slideDown(250).delay(2500).slideUp(250); } }, error: function (err) { console.log(err); }, }); }, }); }); } // 页面初始加载时初始化 $(document).ready(function() { initCommentForms(); }); // 在加载更多评论的AJAX成功回调中调用初始化 $.ajax({ // 加载更多评论的配置 success: function(response) { // 插入新评论到DOM $("#comments-list").append(response.html); // 初始化新表单 initCommentForms(); } });
通过标记已初始化的表单,确保动态加载的表单也能获得完整的验证和AJAX提交逻辑。
内容的提问来源于stack exchange,提问作者Razvan Zamfir
相关产品推荐
相关产品推荐

