Angular 9使用PathLocationStrategy时表单提交如何避免页面重载?
问题根因
你触发了浏览器原生表单提交的默认跳转行为,该行为和Angular的路由策略无关:原生form.submit()执行后,浏览器会直接卸载当前页面加载表单提交后的返回/重定向地址,导致全页重载,此时你之前注册的queryParams订阅会随着应用销毁失效,自然无法触发。
解决方案
方案1:用Angular HttpClient异步提交(推荐)
完全放弃原生表单提交逻辑,改用AJAX异步提交数据,成功后手动通过Angular路由更新查询参数,全程不会触发页面重载。
代码修改
- 调整HTML表单,移除原生提交相关属性:
<form [formGroup]="submitForm" novalidate (ngSubmit)="save()"> <input type="text" formControlName="inputValue"/> <input type="hidden" name="Reference" [value]="data.reference"> <input type="hidden" name="Action" [value]="data.action"> <button class="btn" type="submit">Save</button> </form>
- 修改TS提交逻辑,注入
HttpClient和Router处理提交和路由更新:
import { HttpClient } from '@angular/common/http'; import { Router } from '@angular/router'; // 构造函数注入 constructor( private http: HttpClient, private router: Router ) {} public save() { // 组装表单数据 const submitData = new FormData(); submitData.append('Reference', this.data.reference); submitData.append('Action', this.data.action); submitData.append('inputValue', this.submitForm.value.inputValue); // 异步提交到后端接口 this.http.post(this.data.crnUrl, submitData).subscribe({ next: (res) => { // 提交成功后手动更新路由查询参数,不会触发页面重载 this.router.navigate([], { queryParams: { data: 'new' }, // 可从返回结果res中取实际需要的参数 queryParamsHandling: 'merge' // 保留原有查询参数,不需要可删除 }); }, error: (err) => { // 处理提交异常逻辑 } }) }
方案2:隐藏iframe承接提交(仅适用于必须用原生表单提交的场景,如对接第三方回调要求)
如果后端要求必须走原生表单提交跳转,可将提交的target指向隐藏的iframe,避免主页面被重载,再手动同步参数到主页面路由。
代码修改
- 调整HTML,新增隐藏iframe,给表单设置target指向该iframe:
<iframe name="hiddenSubmitFrame" style="display: none;"></iframe> <form [formGroup]="submitForm" novalidate [id]="submitFormId" method="post" isolate-form target="hiddenSubmitFrame"> <input type="text"/> <input type="hidden" name="Reference" [value]="data.reference"> <input type="hidden" name="Action" [value]="data.action"> <button class="btn" (click)="save()">Save</button> </form>
- 修改TS逻辑,监听iframe加载事件同步查询参数:
import { Router } from '@angular/router'; constructor(private router: Router) {} public save() { const $form = $('#submitFormId'); $form.attr('action', this.data.crnUrl); const iframe = document.querySelector('iframe[name="hiddenSubmitFrame"]'); // 监听iframe加载完成,获取重定向后的参数 const loadHandler = () => { try { // 同域场景可直接读取iframe地址参数 const iframeLocation = new URL(iframe.contentWindow.location.href); const dataParam = iframeLocation.searchParams.get('data'); // 同步参数到主页面路由 this.router.navigate([], { queryParams: { data: dataParam }, queryParamsHandling: 'merge' }); } catch (e) { // 跨域场景需要后端配合返回postMessage通知主页面传递参数 } // 移除监听避免重复触发 iframe.removeEventListener('load', loadHandler); }; iframe.addEventListener('load', loadHandler); $form.submit(); }
内容的提问来源于stack exchange,提问作者ThuyNguyen
相关产品推荐
相关产品推荐

