解决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 之后,我们还是需要不时地复习基础知识。如果大家也遇到了类似的问题,可以参考我的解决方法。

相关推荐
赵啸林2 分钟前
npm发布插件超级简单版
前端·npm·node.js
我码玄黄35 分钟前
THREE.js:网页上的3D世界构建者
开发语言·javascript·3d
罔闻_spider36 分钟前
爬虫----webpack
前端·爬虫·webpack
吱吱鼠叔37 分钟前
MATLAB数据文件读写:1.格式化读写文件
前端·数据库·matlab
爱喝水的小鼠1 小时前
Vue3(一) Vite创建Vue3工程,选项式API与组合式API;setup的使用;Vue中的响应式ref,reactive
前端·javascript·vue.js
小晗同学1 小时前
Vue 实现高级穿梭框 Transfer 封装
javascript·vue.js·elementui
WeiShuai1 小时前
vue-cli3使用DllPlugin优化webpack打包性能
前端·javascript
Wandra1 小时前
很全但是超级易懂的border-radius讲解,让你快速回忆和上手
前端
forwardMyLife1 小时前
element-plus的面包屑组件el-breadcrumb
javascript·vue.js·ecmascript
ice___Cpu1 小时前
Linux 基本使用和 web 程序部署 ( 8000 字 Linux 入门 )
linux·运维·前端