You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask表单提交显示Spinner后页面无法重新渲染问题求助

Flask表单提交显示Spinner并正常渲染页面的解决方案

问题出在哪?

你用XMLHttpRequest提交表单后,浏览器不会自动刷新页面——原来的表单默认提交是直接跳转刷新,而XHR是异步请求,得手动把服务器返回的HTML内容替换到页面上,不然页面就不会更新。另外,之前的代码没阻止表单的默认提交行为,可能导致XHR和默认跳转冲突。

修正后的前端代码

先调整HTML结构(保留你原有的表单,加上Spinner和结果展示区):

<form id="questions" method="POST">
  <textarea name="user_input" id="user_input" placeholder="输入你的问题..."></textarea>
  <button type="submit">提交</button>
  <!-- 默认隐藏的Spinner -->
  <div id="spinner" style="display: none;">正在处理,请稍候...</div>
  <!-- 用来展示结果的区域 -->
  <div id="result-container"></div>
</form>

然后重写JavaScript逻辑:

const form = document.getElementById('questions');
const spinner = document.getElementById('spinner');
const resultContainer = document.getElementById('result-container');

form.addEventListener('submit', function(e) {
  // 先阻止表单默认跳转,不然XHR还没跑页面就刷新了
  e.preventDefault();
  
  // 显示Spinner
  spinner.style.display = 'block';
  
  // 自动收集表单里的所有数据
  const formData = new FormData(form);
  
  // 创建异步请求对象
  const xhr = new XMLHttpRequest();
  
  // 配置请求:POST方法,表单的提交地址,异步模式
  xhr.open('POST', form.action, true);
  
  // 请求成功完成时的处理
  xhr.onload = function() {
    // 先把Spinner藏起来
    spinner.style.display = 'none';
    
    if (xhr.status === 200) {
      // 把服务器返回的HTML替换到结果容器里
      resultContainer.innerHTML = xhr.responseText;
      // 如果后端返回的是完整页面,也可以替换整个页面内容:
      // document.body.innerHTML = xhr.responseText;
    } else {
      resultContainer.innerHTML = '提交失败,请重试';
    }
  };
  
  // 请求出错时的处理
  xhr.onerror = function() {
    spinner.style.display = 'none';
    resultContainer.innerHTML = '网络出错了,请检查连接';
  };
  
  // 发送表单数据
  xhr.send(formData);
});

后端Flask代码的小调整(可选)

如果想让后端区分普通请求和AJAX请求,只返回结果部分而不是完整页面,可以改一下视图函数:

from flask import Flask, render_template, request

app = Flask(__name__)

# 存储用户输入的列表(实际项目建议用数据库,这里只是示例)
input_records = []

@app.route('/', methods=['GET', 'POST'])
def handle_form():
    if request.method == 'POST':
        user_input = request.form.get('user_input')
        if user_input:
            input_records.append(user_input)
            # 模拟耗时操作,测试Spinner效果
            import time
            time.sleep(2)
    
    # 判断是不是AJAX请求(XHR会自动带这个请求头)
    if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
        # 只返回结果部分的HTML
        return render_template('result_content.html', records=input_records)
    else:
        # 普通请求返回完整页面
        return render_template('index.html', records=input_records)

然后拆分模板:

  • index.html(完整页面):
<!DOCTYPE html>
<html>
<head>
    <title>我的Flask应用</title>
</head>
<body>
    <form id="questions" method="POST">
        <textarea name="user_input" placeholder="输入内容..."></textarea>
        <button type="submit">提交</button>
        <div id="spinner" style="display: none;">正在处理...</div>
    </form>
    <div id="result-container">
        {% include 'result_content.html' %}
    </div>
    <script>
        <!-- 上面的JS代码 -->
    </script>
</body>
</html>
  • result_content.html(仅结果部分):
<h3>已提交的内容</h3>
<textarea readonly rows="6">
{% for item in records %}
{{ item }}
{% endfor %}
</textarea>

核心要点

  1. 必须阻止表单默认行为:用e.preventDefault()拦住表单的自动跳转,不然XHR请求还没完成,页面就刷新了,Spinner自然没效果。
  2. 手动处理XHR响应:XHR是异步请求,浏览器不会自动更新页面,得在onload事件里把服务器返回的内容插入到页面指定位置。
  3. Spinner状态管理:提交前显示,请求结束(不管成功失败)都要隐藏,给用户明确的反馈。

内容的提问来源于stack exchange,提问作者Shanahando

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 00:11:06