为什么JavaScript代码导致Laravel Blade视图的提交按钮失效
问题根因与修复方案
核心问题
- 非法表单嵌套:HTML规范明确禁止
<form>标签嵌套,浏览器解析时会自动丢弃内层嵌套的发送验证码表单标签,导致你后续动态插入的「重新发送验证码」submit按钮实际归属外层的登录表单,dom结构解析异常直接导致原有的登录提交按钮行为失效。你注释JS后没有新增额外的submit按钮,嵌套带来的异常影响未触发,所以按钮恢复正常。 - 重复ID冲突:
verify_code和send_code两个分支下都使用了id="timer"、id="txt",HTML要求ID全局唯一,document.getElementById只会匹配到第一个对应ID的元素,会导致定时器逻辑执行异常。 - 动态插入的重发提交按钮缺少Laravel要求的CSRF Token,就算提交也会触发419状态码错误。
修复方案
- 移除嵌套的内层表单,把重发验证码逻辑放到外层单独的表单,避免表单嵌套。
- 合并重复的提示块代码,保证ID全局唯一。
- 动态插入按钮时补全CSRF校验逻辑。
修正后表单代码示例
<!-- 外层登录表单 --> <form action="{{ route('do.verify.phone') }}" method="post" class="pt-2"> @csrf @if($m = Session('verify_unsuccessful')) <div class="form-group mb-3"> <div class="alert alert-danger"> <ul> <li>{{$m}}</li> </ul> </div> </div> @endif <!-- 合并重复的验证码提示块 --> @if (Session('verify_code') || Session('send_code')) <div class="form-group mb-3"> <div class="alert alert-primary"> <div id="timer"></div> <p>若30秒内未收到验证码,请稍后重试</p> <div id="txt"></div> </div> </div> @endif <div class="form-group mb-3"> <label for="code">验证码</label> <input name="code" type="text" class="form-control" placeholder="请输入发送到您手机的验证码" autofocus> </div> <div class="form-group mb-0 text-center"> <button class="btn btn-success btn-block" type="submit"> 登录</button> </div> </form> <!-- 单独放置重发验证码的表单,不嵌套 --> <form action="{{ route('send.code') }}" method="post" id="resendForm" class="d-none"> @csrf </form>
修正后JS代码示例
<script> var seconds = 30; var timer; function myFunction() { const timerDom = document.getElementById("timer"); if(!timerDom) return; if(seconds < 60) { timerDom.innerHTML = seconds + '秒后可重新发送验证码'; } if (seconds > 0) { seconds--; } else { clearInterval(timer); // 插入重发按钮,绑定独立的提交逻辑 document.getElementById('txt').innerHTML = '<button type="button" class="btn btn-outline-primary" id="resendBtn">重新发送验证码</button>'; document.getElementById('resendBtn').addEventListener('click', function() { document.getElementById('resendForm').submit(); }); } } window.onload = function() { // 只有存在计时器元素时才启动定时器,避免无提示块时JS报错 if(document.getElementById("timer") && !timer) { timer = window.setInterval(myFunction, 1000); } } </script>
内容的提问来源于stack exchange,提问作者foad
相关产品推荐
相关产品推荐

