日常踩坑记录

本篇文章主要介绍一下最近的开发中用到的些小问题。问题不大,但有些小细节,记录一下,有遇到的朋友可以看一下,有更好的解决方法欢迎分享。

浏览器记住密码自动填充表单

这个问题我在火狐浏览器遇到了。我登录系统时选择了浏览器记住密码;然后在打开新建数据库弹窗,里面的户名和密码竟然自动填充了。设置了autoComplete=“off”,也没有用,这个只是为了关闭输入提示。以下时具体的解决方法,亲测有效

import React from "react";
import { Button, Form, Input } from "antd";

const MyForm: React.FC = () => {
  const [form] = Form.useForm();
  const onFinish = (values: any) => {
    console.log("Success:", values);
  };

  const onFinishFailed = (errorInfo: any) => {
    console.log("Failed:", errorInfo);
  };

  /** 清空密码 */
  const resetPass = () => {
    if (!form.isFieldTouched("password")) {
      form.setFieldsValue({ password: "" });
    }
  };

  /** 清空用户名 */
  const resetUser = () => {
    if (!form.isFieldTouched("username")) {
      form.setFieldsValue({ username: "" });
    }
  };

  return (
    <Form
      name="basic"
      form={form}
      labelCol={{ span: 8 }}
      wrapperCol={{ span: 16 }}
      initialValues={{ remember: true }}
      onFinish={onFinish}
      onFinishFailed={onFinishFailed}
      autoComplete="off"
    >
      <Form.Item
        label="IP"
        name="ip"
        rules={[{ required: true, message: "Please input your ip!" }]}
      >
        <Input />
      </Form.Item>
      <Form.Item
        label="Port"
        name="port"
        rules={[{ required: true, message: "Please input your port!" }]}
      >
        <Input />
      </Form.Item>
      {/* 用于干扰浏览器记住密码 */}
      <Form.Item style={{ display: "none" }}>
        <Input onFocus={resetUser}/>
      </Form.Item>
      <Form.Item style={{ display: "none" }}>
        <Input.Password onFocus={resetPass}/>
      </Form.Item>
      <Form.Item
        label="Username"
        name="username"
        rules={[{ required: true, message: "Please input your username!" }]}
      >
        <Input onFocus={resetUser} />
      </Form.Item>

      <Form.Item
        label="Password"
        name="password"
        rules={[{ required: true, message: "Please input your password!" }]}
      >
        <Input.Password onFocus={resetPass} autoComplete="off"/>
      </Form.Item>

      <Form.Item wrapperCol={{ offset: 8, span: 16 }}>
        <Button type="primary" htmlType="submit">
          Submit
        </Button>
      </Form.Item>
    </Form>
  );
};

export default MyForm;

具体来说,在代码中添加了两个隐藏的,一个用于用户名(Input类型),另一个用于密码(Input.Password类型),然后分别在这两个元素的onFocus事件中调用了resetUser和resetPass函数,这两个函数在字段没有被触摸(touched)过的情况下将字段值设置为空字符串。

这样的做法会使浏览器的自动填充机制失效,因为浏览器通常在填充用户凭据之前会检查字段是否为空。这是一种常见的防止浏览器自动填充密码的方法。

不过需要注意的是,浏览器的自动填充机制可能会随着时间的推移而改变,因此这种解决方案可能不是绝对稳定的。不过暂时我的页面没出现问题。

ant Design下拉框,下拉菜单、日历等组件随页面滚动问题

在antd中下拉框组件有很多比如: Select、Dropdown、DatePicker等,在点击后会出现下拉选择框,但是当滚动页面时,会发现下拉框固定不动。
分析:

  1. 定位问题:某些情况下,组件的定位可能会受到父元素、祖先元素的定位影响。确保你的组件的定位设置正确,可以使用 CSS 的 positiontopleft 等属性来控制定位。

  2. 层叠上下文:在 CSS 中,每个元素都位于一个层叠上下文中,层叠上下文可以影响元素的渲染和布局。如果组件的父元素或祖先元素具有不同的层叠上下文属性,可能会导致组件的位置不正确。了解层叠上下文的工作原理,并适当地设置元素的 z-index 属性,可以帮助解决这类问题。

  3. Fixed 定位:如果你希望组件在页面滚动时保持固定位置,可以考虑使用 CSS 中的 position: fixed。这将使组件相对于浏览器窗口固定位置,而不受页面滚动的影响。

解决方案:
根据官方文档提供的api可以看到,有个getPopupContainer参数,可以改变下拉弹窗的渲染节点。默认是被渲染到body的,所以虽然父容器发生滚动,弹窗位置依旧不动。
在这里插入图片描述

import React from 'react';
import { Select } from 'antd';

const Option = Select.Option;

const Hello = () => (
  <div style={{ margin: 10, overflow: 'scroll', height: 200 }}>
    <h2>Select in a scrollable area</h2>
    <div style={{ padding: 100, height: 1000, background: '#eee', position: 'relative' }} id="area">
      <h4>可滚动的区域 / scrollable area</h4>
      <Select
        defaultValue="lucy"
        style={{ width: 120 }}
        getPopupContainer={() => document.getElementById('area')!}
      >
        <Option value="jack">Jack</Option>
        <Option value="lucy">Lucy</Option>
        <Option value="yiminghe">yiminghe</Option>
      </Select>
    </div>
  </div>
);

export default Hello;

上面面是官网给的使用例子。就是通过id将下拉弹窗绑定到滚动区域。
这样确实能解决滚动问题,但是在滚动区域的高度或者宽度不够时,下拉弹窗的位置也会发生错位,导致样式不好看。
如果在页面高度和宽度允许的情况下,可以世道调整滚动容器的大小。由于我的下拉框时放在Modal弹窗里,滚动高度是限的,所以我使用了动态改变下拉框的渲染容器,当页面不需要滚动时就挂载到body。滚动就挂载到滚动容器上。

修改上述代码:

import React, { useRef, useState } from "react";
import { Select } from "antd";

const Option = Select.Option;

const Hello = () => {
  const conRef = useRef<any>();
  const [open, setOpen] = useState<boolean>(false); // 每次打开下拉框重新渲染挂载节点
 /** 动态获取挂载节点 */
  const getContainer = () => {
    if (conRef?.current?.scrollHeight > 400) {
      return conRef?.current;
    }
    return document.body;
  };
  return (
    <div style={{ margin: 10, overflow: "scroll", height: 200 }}>
      <h2>Select in a scrollable area</h2>
      <div
        style={{
          padding: 100,
          height: 1000,
          background: "#eee",
          position: "relative",
        }}
        id="area"
        ref={conRef}
        key={`${open}`}
      >
        <h4>可滚动的区域 / scrollable area</h4>
        <Select
          defaultValue="lucy"
          style={{ width: 120 }}
          getPopupContainer={() => getContainer()}
          onDropdownVisibleChange={(e) => setOpen(e)}
        >
          <Option value="jack">Jack</Option>
          <Option value="lucy">Lucy</Option>
          <Option value="yiminghe">yiminghe</Option>
        </Select>
      </div>
    </div>
  );
};

export default Hello;

在下拉框打开时,根据滚动区域的高度决定下拉框的渲染容器,以避免下拉框的内容溢出可视区域。key={${open}} 的作用是为了在每次下拉框打开或关闭时触发一个新的 key,从而触发重新渲染。

Table 表格拖拽自适应宽度

当我在实现表格可拖拽列宽度时,有时候表格整体宽度不够时,其他列也会跟着变化。这是因为ant design 会调整列的宽度,为了解决这个问题,可以加个空白列去适应多余宽度。
类似以下代码。
ResizableTable.tsx是我根据react-resizable插件封装的Table组件。需要代码可私聊

import React from 'react';
import ResizableTable from './ResizableTable.tsx';

const columns = [
  {
    title: 'Name',
    dataIndex: 'name',
    width: 150,
  },
  {
    title: 'Age',
    dataIndex: 'age',
    width: 80,
  },
  {
    title: 'Address',
    dataIndex: 'address',
    width: 200,
  },
  {
    title:'', // 用于自适应多余宽度
    dataIndex:'null'
  }
];

const dataSource = [
  {
    key: '1',
    name: 'John Brown',
    age: 32,
    address: 'New York No. 1 Lake Park',
  },
  // ...more data
];

const App = () => {
  return <ResizableTable columns={columns} dataSource={dataSource} />;
};

export default App;

你可能感兴趣的:(React,前端,Ant,Design)