Rails 5.1中Ajax提交后JSON渲染至页面而非执行回调问题
问题分析与解决方案
这个问题的核心原因非常明确:你在发起Ajax请求前手动触发了表单的默认提交行为,直接导致浏览器执行了传统的页面跳转,完全绕过了你的Ajax回调逻辑。下面一步步拆解问题并给出修复方案:
问题根源
你代码里的$form.get(0).submit();会立刻触发表单的默认提交流程——浏览器会直接发送表单请求并跳转页面,而你后续写的Ajax请求虽然会发起,但页面已经跳转了,.done()回调根本没机会执行。另外,你把return false放在.done()里也是无效的,因为这个回调要等Ajax成功才会运行,而默认提交的跳转早已经发生了。
修复方案(两种可选)
方案一:手动拦截表单提交,自己实现Ajax
移除手动触发的submit()调用,改为监听表单的submit事件,在事件触发时先阻止默认行为,再发起Ajax请求:
// 监听表单提交事件 $form.on('submit', function(e) { // 阻止浏览器的默认表单提交行为 e.preventDefault(); var jqxhr = $.ajax({ url: '/give', type: 'POST', dataType: 'json', data: $(this).serialize() }) .done(function(response) { console.log(response); $('#new-gift').hide(function() { $('#confirm-gift').show(); }); }) .fail(function() { // 这里可以添加错误提示逻辑,比如显示验证失败信息 }) .always(function() { }); // 双重保险,再次阻止默认行为 return false; });
方案二:利用Rails的remote: true特性(更符合Rails风格)
你已经在表单里加了remote: true,Rails自带的jquery_ujs会自动把这个表单的提交转为Ajax请求,不需要自己手动写$.ajax:
- 先确认Webpacker里正确导入了
jquery_ujs(在app/javascript/packs/application.js里添加):
import 'jquery' import 'jquery_ujs'
- 替换你的JavaScript代码为监听Rails的Ajax事件:
// 监听Ajax成功事件 $form.on('ajax:success', function(e, responseData) { console.log(responseData); $('#new-gift').hide(function() { $('#confirm-gift').show(); }); }) // 监听Ajax失败事件(比如验证不通过) .on('ajax:error', function(e, xhr) { var errors = xhr.responseJSON?.errors; // 这里可以处理错误,比如显示错误提示 });
同时完全移除你原来的$.ajax代码和手动submit()调用——remote: true会自动帮你阻止默认提交、发起Ajax请求。
额外优化建议
你的控制器代码在验证失败时没有返回任何响应,建议补充这部分逻辑,方便前端处理错误:
def create @giver = Giver.new(giver_params) if @giver.save render json: { location: 'url' }, status: :ok else # 返回验证错误信息和对应状态码 render json: { errors: @giver.errors.full_messages }, status: :unprocessable_entity end end
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

