为何在HTML中添加<form>会导致JavaScript与Flask交互功能失效?
表单包裹元素后AJAX更新DOM失效的原因
当把页面中两个输入框和按钮用<form>标签包裹后,原本通过JavaScript的fetch请求获取Flask服务器返回文本、并更新<blockquote>内容的功能就失效了。以下是问题成因分析:
原可正常工作的代码
HTML代码
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="utf-8" /> <link rel="stylesheet" href="{{ url_for('static', filename='CSSsheets/SBPstyle.css') }}" /> <title></title> </head> <body> <input id="expertiseReq" placeholder="leave blank for any skill level" /> <input id="locationReq" placeholder="leave blank for any location" /> <button id="gatherNames">Click to Get List of Player Names</button> <blockquote id="playerNamesGoHere" class="properly_sized_blockquote">No Player Names Loaded</blockquote> <script src="{{ url_for('static', filename='JSscripts/SBPscript.js') }}"></script> </body> </html>
CSS代码
.properly_sized_blockquote { border: solid; border-block-width: 20px; height: 600px; width: 150px; }
JavaScript代码
const gatherPlayersButton = document.getElementById('gatherNames'); const areaForPlayerNames = document.getElementById('playerNamesGoHere') const summon_players = () => { let eR let lR if (document.getElementById('expertiseReq').value == "") { eR = "None"; } else { eR = document.getElementById('expertiseReq').value }; if (document.getElementById('locationReq').value == "") { lR = "None"; } else { lR = document.getElementById('locationReq').value }; let tagsString = eR + "," + lR; fetch(`/battle?tags=${tagsString}`, { method: "GET" }).then((response) => response.text()).then((text) => { areaForPlayerNames.innerText = text; }); }; gatherPlayersButton.addEventListener("click", () => summon_players());
Flask服务器代码
from flask import Flask, render_template, request from static.SNEKfiles import SpaceShipGame import json game_app = Flask(__name__) @game_app.route('/') @game_app.route('/home') def home(): return render_template("HTMLPage1.html") @game_app.route('/battle', methods=['GET', 'POST']) def battle(): if request.method == 'GET': gathering_player_requirements = request.args.get('tags') if gathering_player_requirements != None: print(gathering_player_requirements) skill_requirement = gathering_player_requirements.split(",")[0] location_requirement = gathering_player_requirements.split(",")[1] gathering_player = SpaceShipGame.Player() gathered_player_names = gathering_player.obtainAllPlayerNames(skill_requirement, location_requirement) return gathered_player_names else: return render_template("SingleBattlePage.html")
问题成因分析
核心原因是表单内的按钮默认会触发表单提交行为:
- 当按钮被包裹在
<form>标签内时,如果没有显式指定type="button",浏览器会默认把这个按钮识别为type="submit"(提交按钮)。 - 点击这个按钮时,浏览器会先执行表单的默认提交逻辑:按照表单的
action属性(未指定则提交到当前页面URL)发起请求,同时刷新整个页面。 - 虽然你的JavaScript代码也绑定了click事件并发起了fetch请求,但页面刷新的速度会比fetch请求的回调执行更快——页面刷新后,原来的DOM元素被重新渲染,fetch回调里更新
<blockquote>的操作根本来不及生效,自然看不到服务器返回的文本。
而在没有<form>包裹的情况下,按钮没有默认的提交行为,click事件绑定的fetch请求能正常完成,回调可以顺利更新<blockquote>的内容。
内容的提问来源于stack exchange,提问作者Frasher Gray
相关产品推荐
相关产品推荐

