Yii框架Ajax表单提交触发两次请求的问题排查与解决
问题分析与解决
一、Ajax请求触发两次的原因
- Yii ActiveForm内置校验请求:你开启了
enableAjaxValidation = true和validateOnSubmit = true,这会让Yii在表单提交时自动发起一次Ajax请求做模型校验。 - 自定义提交事件请求:你额外绑定了表单的
submit事件,手动发起了一次Ajax提交,两者叠加导致两次请求。
二、阻止重复请求的几种方案
方案1:关闭Yii内置的提交时校验(最简单)
如果不需要提交前的Ajax模型校验,直接修改ActiveForm配置:
$form = ActiveForm::begin([ 'id' => $model->formName(), 'enableAjaxValidation' => false, // 关闭Ajax校验 'enableClientValidation'=> false, 'validateOnBlur' => false, 'validateOnChange' => false, 'validateOnSubmit' => false, // 关闭提交时自动校验 'options' => ['autocomplete' => 'off'], ]);
这样就只有你自定义的submit事件会发起请求。
方案2:保留Ajax校验,复用Yii事件逻辑
如果需要保留提交前校验,不要自己绑定submit事件,改用Yii ActiveForm的beforeSubmit事件,在校验通过后再发起提交:
$(document).ready(function () { var $form = $("#<?= $model->formName() ?>"); $form.on("beforeSubmit", function (event) { event.preventDefault(); $.ajax({ "type":"POST", "url":$form.attr('action'), "data":$form.serialize(), "dataType":"json", "cache": false, // 表单提交建议关闭缓存 "success":function(data){ if (data.tax) { $("#tax").html(data.tax); } } }); return false; }); });
后端保持enableAjaxValidation = true和validateOnSubmit = true即可,Yii会先完成校验,通过后才触发beforeSubmit事件。
方案3:在自定义事件中区分校验触发的提交
Yii触发submit时会传递messages参数,可通过该参数判断是否为校验导致的提交,只处理自定义逻辑:
$(document).ready(function () { var $form = $("#<?= $model->formName() ?>"); $form.on("submit", function (event, messages) { // 存在messages说明是Yii校验触发的submit,直接返回 if (messages) return; event.preventDefault(); event.stopImmediatePropagation(); $.ajax({ "type":"POST", "url":$form.attr('action'), "data":$form.serialize(), "dataType":"json", "cache": false, "success":function(data){ $("#tax").html(data.tax); } }); return false; }); });
三、正确更新计算结果到指定div的问题
你后端执行calculatetax()后直接die;,没有返回JSON数据,前端根本拿不到data.tax。需要修改后端代码,返回包含计算结果的JSON响应:
if ($model->validate()) { $taxResult = $this->calculatetax(); // 假设calculatetax()返回计算结果 Yii::$app->response->format = Response::FORMAT_JSON; return ['tax' => $taxResult]; // 去掉die;,让Yii正常输出JSON响应 }
内容的提问来源于stack exchange,提问作者Shaho
相关产品推荐
相关产品推荐

