解决React中的隐藏陷阱:点击按钮导致的页面刷新和URL变化

背景

在一个悠闲的午后,旁边的同事突然一脸严肃地问我:"为什么在 form 表单中点击一个按钮会导致我的 Web 页面刷新?"我一时愣住了,因为这样的问题我从未遇到过,涉及到了我的知识盲区。当我观察他的操作时,确实发现页面刷新了。然后我尝试将他的业务代码全部删除,只保留 form 标签和 button,结果点击仍然刷新了页面。

css 复制代码
<form>
  <button>保存设置</button>
  <button>取消</button>
</form>

http://localhost:3000 变成了 http://localhost:3000/?,页面也刷新了。百思不得其解

分析

接着,我尝试使用 antd 组件库 进行测试,发现一切正常。点击按钮并没有触发页面的刷新,令人费解

javascript 复制代码
import { Button, Form } from 'antd';
function App() {
  return (
    <Form>
      <Button>Submit</Button>
    </Form>
  );
}

我开始思考,这和原生的编写方式有什么不同吗?于是我开始检查页面元素,看看是否有什么不同。灵机一动,我发现 antd 组件库编译之后的 button 多了一个 type="button" 的设置,难道这就是答案吗?

验证

于是我在原生标签的 button 上添加了 type="button",发现问题得到了解决,点击按钮后,页面不再刷新!同事直呼 牛啊~。但作为一名具有工匠精神的程序员,我带着问题和答案,想进一步探究这个问题的根源。

一番努力,偶然在 MDN Web 文档 - <button> 上找到了相关的介绍

如果你的按钮不是用于向服务器提交数据,请确保这些按钮的 type 属性设置成 button。否则它们被按下后将会向服务器发送数据并加载(可能并不存在的)响应内容,因而可能会破坏当前文档的状态。

有点意思,翻译成大白话就是:当一个按钮位于 <form> 标签内且没有指定 type 属性时,它的默认行为是提交表单。当表单提交时,浏览器会进行以下操作:

  1. 收集表单内所有输入字段的值。
  2. 根据 <form> 标签的 method 属性(默认为 GET)和 action 属性(默认为当前页面URL)来确定提交的方式和目标。
  3. 提交表单数据,并根据 method 属性将数据添加到URL(如果是 GET 方法)或请求体(如果是 POST 方法)。

真相大白

在一个标准的 HTML 表单中,如果你没有指定 action 属性,表单提交后的目标 URL 将会是当前页面的 URL。同时,如果你没有指定 method 属性默认就是 GET 方法,浏览器会将表单数据以 查询字符串 的形式添加到 URL 中。

查询字符串 是 URL 中 ? 后面的部分,用于传递额外的参数。http://localhost:3000/? 中的 ? 就是查询字符串的开始。如果表单中没有任何数据,或者数据都为空,查询字符串 就只有?,没有任何参数。

所以,当你点击 type 属性为 submit(或未指定 type 属性)的按钮提交表单时,如果表单未指定 method 属性,并且未指定 action 属性,浏览器就会将表单数据以 查询字符串 的形式添加到当前页面 URL 中,从而导致 URL 变为 http://localhost:3000/?

解决方法

要解决这个问题,可以采取以下两种措施:

方法1:将按钮类型设置为 button

将按钮的 type 属性设置为 button,这样它就不会触发表单提交,从而避免修改浏览器URL。

jsx 复制代码
<form>
  <Button type="button">保存设置</Button>
  <Button type="button">取消</Button>
</form>

方法2:阻止表单提交

在表单的onSubmit事件处理函数中调用preventDefault()方法,阻止表单提交。这样,即使按钮的类型是submit,也不会触发表单提交。

jsx 复制代码
import React from 'react';

const MyForm = () => {
  const handleSubmit = (event) => {
    event.preventDefault(); // 阻止表单提交
    // 处理表单提交的逻辑
  };

  return (
    <form onSubmit={handleSubmit}>
      <Button>保存设置</Button>
      <Button type="button">取消</Button>
    </form>
  );
};

export default MyForm;

这两种方法都可以防止点击按钮时修改浏览器URL。通过使用这些方法,你可以确保按钮不会触发表单提交,从而避免修改浏览器URL和页面刷新。

结论

原本同事直接使用 antd 组件库 就很好,偏偏要自己敲代码。作为一条咸鱼,我们不应该总是想着自己造轮子,直接使用第三方组件库能避免很多问题,既省时又省力,避免了不必要的麻烦。另外,长时间使用 Ctrl C + Ctrl V 之后,我们还是需要不时地复习基础知识。如果大家也遇到了类似的问题,可以参考我的解决方法。

相关推荐
待磨的钝刨12 分钟前
【格式化查看JSON文件】coco的json文件内容都在一行如何按照json格式查看
开发语言·javascript·json
逐·風3 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
Devil枫4 小时前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试
尚梦4 小时前
uni-app 封装刘海状态栏(适用小程序, h5, 头条小程序)
前端·小程序·uni-app
GIS程序媛—椰子5 小时前
【Vue 全家桶】6、vue-router 路由(更新中)
前端·vue.js
前端青山5 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
毕业设计制作和分享6 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
从兄6 小时前
vue 使用docx-preview 预览替换文档内的特定变量
javascript·vue.js·ecmascript
清灵xmf7 小时前
在 Vue 中实现与优化轮询技术
前端·javascript·vue·轮询
大佩梨7 小时前
VUE+Vite之环境文件配置及使用环境变量
前端