searchForm自适应布局 + 按钮插槽

news2025/2/26 6:12:21

收起

在这里插入图片描述

展开

在这里插入图片描述

代码:

useResizeObserverHooks.js

import { useEffect, useLayoutEffect } from "react";

export const useResizeObserver = (containerDom, domClass, callback) => {
  useLayoutEffect(() => {
    let resizeObserver = null;
    let dom = null;

    if (typeof ResizeObserver !== "undefined") {
      // 选择你想要观察的元素
      const container = containerDom || document;
      dom = container.querySelector(domClass);

      // 创建一个 ResizeObserver 实例并传入回调函数
      resizeObserver = new ResizeObserver(entries => {
        // 循环遍历所有观察到变化的元素
        for (const entry of entries) {
          const height = entry.target.offsetHeight;
          callback(height);
        }
      });

      // 开始观察元素
      if (dom) {
        resizeObserver?.observe(dom);
      }
    } else {
      console.log("ResizeObserver is not supported in this browser.");
    }
    return () => {
      if (dom) {
        resizeObserver.unobserve(dom);
        resizeObserver?.disconnect(dom);
      }
    };
  }, [containerDom, domClass, callback]);
};


import React, { useState } from "react";
import { Button, ConfigProvider, Space, Form, Flex } from "antd";
import styles from "./Index.module.less";
import { useResizeObserver } from "./useResizeObserverHooks";

const classnames = (...args) => {
  return args.filter(Boolean).join(" ");
};

const SearchForm = props => {
  const {
    defaultHeight = 58,
    children,
    onResetHandle,
    buttomSolt,
    submitText = "查询",
    resetText = "重置",
    ...FromProps
  } = props;
  // const [form] = Form.useForm();
  // console.log(buttomSolt, "buttomSolt");
  const [showMore, setShowMore] = useState(false);
  const containerRef = useRef(null);

  useResizeObserver(containerRef.current,".ant-form", h => {
    setShowMore(h > defaultHeight);
  });

  const onReset = () => {
    // form.resetFields();
    onResetHandle && onResetHandle();
  };
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div
     ref={containerRef}
      style={{ height: `${isOpen ? "auto" : `${defaultHeight}px`}` }}
      className={classnames(
        styles.searchForm,
        !isOpen ? styles.overflowhidden : "",
      )}>
      <ConfigProvider
        theme={{
          token: {
            borderRadius: 4,
          },
        }}>
        <Form {...FromProps}>
          <div className={styles.formItemBox}>{children}</div>
          <div
            className={styles.ButtonBox}
            style={{
              paddingBottom: `${isOpen ? "" : "4px"}`,
              height: `${isOpen ? "auto" : `${defaultHeight}px`}`,
            }}>
            <Form.Item>
              {buttomSolt ? (
                buttomSolt
              ) : (
                <>
                  <Button htmlType="button" onClick={onReset}>
                    {resetText}
                  </Button>
                  <Button type="primary" htmlType="submit">
                    {submitText}
                  </Button>
                </>
              )}
            </Form.Item>
          </div>
        </Form>
      </ConfigProvider>
      {/* 展开 收起 */}
      {isOpen ? <div className={styles.zhanweibefore}></div> : null}
      {showMore ? (
        <div
          className={isOpen ? styles.before : styles.topBefore}
          onClick={() => {
            setIsOpen(e => !e);
          }}>
          <div></div>
        </div>
      ) : null}
    </div>
  );
};

export default SearchForm;

样式

.overflowhidden {
  overflow: hidden;
}
.searchForm {
  color: #666666;
  position: relative;
  .formItemBox {
    display: flex;
    align-items: flex-start;
    justify-content: flex-start;
    flex-wrap: wrap;
    flex: 1;
  }
  .topBefore {
    position: absolute;
    bottom: 0;
    background: #fff;
    border-bottom: 1px solid #dce6ec;
    width: 100%;
    display: flex;
    justify-content: center;
    cursor: pointer;
    > div {
      width: 74px;
      height: 4px;
      background: #b3d9ff;
      position: relative;
      cursor: pointer;
      &::before {
        content: "";
        width: 0;
        height: 0;
        border-left: 5px solid transparent;
        border-right: 5px solid transparent;
        border-bottom: 10px solid #b3d9ff;
        position: absolute;
        top: -2px;
        left: 50%;
        transform: translate(-50%, -50%);
      }
    }
  }
  .zhanweibefore {
    width: 100%;
    height: 14px;
  }
  .before {
    position: absolute;
    bottom: 0;
    background: #fff;
    width: 100%;
    height: 14px;
    display: flex;
    justify-content: center;
    border-top: 1px solid #dce6ec;
    > div {
      width: 74px;
      height: 4px;
      background: #b3d9ff;
      position: relative;
      cursor: pointer;
      &::before {
        content: "";
        width: 0;
        height: 0;
        border-left: 5px solid transparent;
        border-right: 5px solid transparent;
        border-top: 10px solid #b3d9ff;
        position: absolute;
        top: 7px;
        left: 50%;
        transform: translate(-50%, -50%);
      }
    }
  }

  .ButtonBox {
    width: 200px;
    height: 100%;
    display: flex;
    align-items: flex-end;
    justify-content: flex-end;
    :global {
      .ant-btn {
        padding: 4px 10px;
        margin-right: 10px;
      }

      // 重置插槽内样式
      .ant-form-item-control-input-content {
        align-items: flex-end;
        justify-content: flex-end;
      }
    }
  }
  :global {
    .ant-form {
      //   padding-right: 200px;
      position: relative;
    }

    .ant-form-item {
      display: flex;
      align-items: center;
      width: 290px;
      margin: 0;
      padding: 10px 15px 10px 0;
    }
    .ant-row {
      flex: 1;
      .ant-form-item-label {
        width: 90px;
      }
      .ant-form-item-control {
        flex: 1;
      }
      .ant-form-item-control-input-content {
        display: flex;
        .flex1 {
          flex: 1;
        }
        .flex2 {
          flex: 2;
        }
      }
    }
    .ant-space-compact {
      flex: 1;
      align-items: center;
    }
    .ant-picker,
    .ant-input-number {
      width: 100%;
    }

    .span2 {
      width: 580px;
    }

    .ant-slider {
      width: 100%;
    }
  }
}

使用

查看Antd Form api

 className="span2"
 className="flex2"
 className="flex1"
import React, { useState, useEffect } from "react";
import styles from "./index.module.less";
import SearchForm from "@/components/SearchForm";
import HocAntdTable from "@/components/HocAntdTable";

import {
  Form,
  Space,
  Tag,
  Button,
  Cascader,
  Checkbox,
  ColorPicker,
  DatePicker,
  Input,
  InputNumber,
  Radio,
  Select,
  Slider,
  Switch,
  TreeSelect,
  Upload,
} from "antd";

const { RangePicker } = DatePicker;
const { TextArea } = Input;

const mockDataSource = Array.from({ length: 20 }, (_, index) => ({
  key: (index + 1).toString(),
  firstName: ["John", "Jim", "Joe"][index % 3],
  lastName: ["Brown", "Green", "Black"][index % 3],
  age: [32, 42, 32][index % 3],
  address: [
    "New York No. 1 Lake Park",
    "London No. 1 Lake Park",
    "Sydney No. 1 Lake Park",
  ][index % 3],
  tags: [["nice", "developer"], ["loser"], ["cool", "teacher"]][index % 3],
}));
const dataSource = [
  ...mockDataSource,
  {
    key: "1",
    firstName: "John",
    lastName: "Brown",
    age: 32,
    address: "New York No. 1 Lake Park",
    tags: ["nice", "developer"],
  },
  {
    key: "2",
    firstName: "Jim",
    lastName: "Green",
    age: 42,
    address: "London No. 1 Lake Park",
    tags: ["loser"],
  },
  {
    key: "3",
    firstName: "Joe",
    lastName: "Black",
    age: 32,
    address: "Sydney No. 1 Lake Park",
    tags: ["cool", "teacher"],
  },
  {
    key: "11",
    firstName: "John",
    lastName: "Brown",
    age: 32,
    address: "New York No. 1 Lake Park",
    tags: ["nice", "developer"],
  },
  {
    key: "22",
    firstName: "Jim",
    lastName: "Green",
    age: 42,
    address: "London No. 1 Lake Park",
    tags: ["loser"],
  },
  {
    key: "33",
    firstName: "Joe",
    lastName: "Black",
    age: 32,
    address: "Sydney No. 1 Lake Park",
    tags: ["cool", "teacher"],
  },
];

const columns = [
  {
    title: "姓名",
    dataIndex: "name",
    key: "name",
  },
  {
    title: "年龄",
    dataIndex: "age",
    key: "age",
  },
  {
    title: "住址",
    dataIndex: "address",
    key: "address",
  },
];

const FormTableDemoPage = props => {
  const [form] = Form.useForm();
  const aa = () => {
    form.resetFields();
  };
  return (
    <>
      {/* 表单搜索 对照antd Api通用 */}
      <SearchForm
        labelAlign="left"
        layout="inline"
        onFinish={values => {
          console.log(values);
        }}
        form={form}
        onFieldsChange={(changedFields, allFields) => {
          console.log(changedFields, allFields);
        }}
        onResetHandle={() => {
          // 重置事件
          form.resetFields();
        }}

        // buttomSolt = {
        //     <div>
        //     <Button>重置</Button>
        //     <Button>定义</Button>
        //     </div>
        // }
      >
        <Form.Item
          className="span1"
          label="Checkbox"
          name="disabled"
          valuePropName="checked">
          <Checkbox>Checkbox</Checkbox>
        </Form.Item>
        <Form.Item label="Address">
          <Space.Compact>
            <Form.Item
              name={["address", "province"]}
              noStyle
              rules={[
                {
                  required: true,
                  message: "Province is required",
                },
              ]}>
              <Select placeholder="Select province">
                <Option value="Zhejiang">Zhejiang</Option>
                <Option value="Jiangsu">Jiangsu</Option>
              </Select>
            </Form.Item>
            <Form.Item
              name={["address", "street"]}
              noStyle
              rules={[
                {
                  required: true,
                  message: "Street is required",
                },
              ]}>
              <Input
                style={{
                  width: "50%",
                }}
                placeholder="Input street"
              />
            </Form.Item>
          </Space.Compact>
        </Form.Item>
        <Form.Item label={null} name="ssss">
          <Select className="flex1">
            <Select.Option value="demo">Demo</Select.Option>
            <Select.Option value="222">Demo</Select.Option>
          </Select>
          <Select className="flex2" name="demo">
            <Select.Option value="demo">Demo</Select.Option>
            <Select.Option value="222">Demo</Select.Option>
          </Select>
        </Form.Item>
        <Form.Item label="Radio" name="Radio">
          <Radio.Group>
            <Radio value="apple"> Apple </Radio>
            <Radio value="pear"> Pear </Radio>
          </Radio.Group>
        </Form.Item>
        <Form.Item label="Input" name="Input">
          <Input />
        </Form.Item>
        <Form.Item label="Select" name="Select">
          <Select>
            <Select.Option value="demo">Demo</Select.Option>
          </Select>
        </Form.Item>
        <Form.Item label="TreeSelect" name="TreeSelect">
          <TreeSelect
            treeData={[
              {
                title: "Light",
                value: "light",
                children: [
                  {
                    title: "Bamboo",
                    value: "bamboo",
                  },
                ],
              },
            ]}
          />
        </Form.Item>
        <Form.Item label="Cascader" name="Cascader">
          <Cascader
            options={[
              {
                value: "zhejiang",
                label: "Zhejiang",
                children: [
                  {
                    value: "hangzhou",
                    label: "Hangzhou",
                  },
                ],
              },
            ]}
          />
        </Form.Item>
        <Form.Item label="DatePicker" name="DatePicker">
          <DatePicker />
        </Form.Item>
        <Form.Item label="RangePicker" className="span2" name="RangePicker">
          <RangePicker />
        </Form.Item>
        <Form.Item label="InputNumber">
          <InputNumber />
        </Form.Item>
        <Form.Item label="Switch" valuePropName="checked" name="Switch">
          <Switch />
        </Form.Item>

        <Form.Item label="Button">
          <Button>Button</Button>
        </Form.Item>
        <Form.Item label="Slider">
          <Slider />
        </Form.Item>
        <Form.Item label="ColorPicker">
          <ColorPicker />
        </Form.Item>
      </SearchForm>

      {/* 表格查看  对照antd Api通用
      <HocAntdTable dataSource={dataSource} columns={columns} />*/}
    </>
  );
};

export default FormTableDemoPage;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1895032.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

8人团队历时半年打造开源版GPT-4o,零延迟演示引爆全网!人人可免费使用!

目录 01 Moshi 02 背后技术揭秘 GPT-4o可能要等到今年秋季才会公开。 然而&#xff0c;由法国8人团队开发的原生多模态Moshi&#xff0c;已经达到了接近GPT-4o的水平&#xff0c;现场演示几乎没有延迟&#xff0c;吸引了大量AI专家的关注。 令人惊讶的是&#xff0c;开源版的…

代码随想录算法训练营第69天:图论7[1]

代码随想录算法训练营第69天&#xff1a;图论7 109. 冗余连接II 卡码网题目链接&#xff08;ACM模式&#xff09;(opens new window) 题目描述 有向树指满足以下条件的有向图。该树只有一个根节点&#xff0c;所有其他节点都是该根节点的后继。该树除了根节点之外的每一个节…

AI大模型:解锁未来职业竞争力的金钥匙

AI元年&#xff1a;大模型的革新力量 随着ChatGPT的震撼登场&#xff0c;2023年被标记为AI元年&#xff0c;大模型以其前所未有的影响力&#xff0c;重塑我们的日常生活和工作方式。从日常的问答对话到复杂的编程辅助&#xff0c;乃至创意图像生成&#xff0c;AI大模型展现出超…

怎么还有人分不清路由器、交换机、光猫、WiFi……你真的都了解吗?

号主&#xff1a;老杨丨11年资深网络工程师&#xff0c;更多网工提升干货&#xff0c;请关注公众号&#xff1a;网络工程师俱乐部 下午好&#xff0c;我的网工朋友。 讲某个具体技术&#xff0c;说不定你头头是道&#xff0c;但关于路由器、交换机、光猫、WiFi的知识细节&…

AI PC(智能电脑)技术分析

一文看懂AI PC&#xff08;智能电脑&#xff09; 2024年&#xff0c;英特尔、英伟达等芯片巨头革新CPU技术&#xff0c;融入AI算力&#xff0c;为传统PC带来质的飞跃&#xff0c;引领智能计算新时代。 2024年&#xff0c;因此被叫作人工智能电脑&#xff08;AI PC&#xff09;…

我尝试了新的 OpenAI 连接器,真太棒了!

我们上个月发布的新连接器将 Open AI 集成简化为仅需几步操作。我实现了聊天完成 API&#xff08;有和没有上下文&#xff09;&#xff0c;并想编写一个关于其工作原理的快速教程。 先决条件 与往常一样&#xff0c;在进入主要构建之前我们需要做一些准备工作。你会需要&…

FFT 简单基础(matlab

使用 fs 进行采样&#xff0c;进行 N点FFT 选择显示0~N/21点的幅值 横坐标对应频率计算公式&#xff1a; fs * n / N 举个梨子&#xff1a; 频率2kHz采样1s&#xff0c;得到2000个点的序列y(n) 对序列y(n)做4096点的FFT 幅值响应对应的横坐标频率…

隐私信息管理体系认证:守护个人信息,筑牢隐私防线

在数字化浪潮汹涌的当下&#xff0c;个人信息安全问题愈发凸显其重要性。随着互联网技术的飞速发展&#xff0c;我们的隐私信息如同裸露在阳光下的沙滩&#xff0c;稍有不慎就可能被不法分子窃取或滥用。因此&#xff0c;构建一个完善的隐私信息管理体系&#xff0c;成为了保障…

实现第一个神经网络

PyTorch 包含创建和实现神经网络的特殊功能。在本节实验中&#xff0c;将创建一个简单的神经网络&#xff0c;其中一个隐藏层开发一个输出单元。 通过以下步骤使用 PyTorch 实现第一个神经网络。 第1步 首先&#xff0c;需要使用以下命令导入 PyTorch 库。 In [1]: import…

免费通配符/泛域名SSL证书快速申请攻略

在互联网时代&#xff0c;网站安全的重要性日益凸显&#xff0c;而SSL证书作为保障网站安全的关键工具&#xff0c;其重要性不言而喻。对于拥有多个子域名的网站来说&#xff0c;通配符/泛域名SSL证书更是必不可少的安全保障。下面将介绍如何申请免费的通配符/泛域名SSL证书。 …

EXTI寄存器,AFIO的简洁,EXTI配置的流程

一&#xff0c;AFIO简介 AFIO是Alternate Function Input/Output 的缩写&#xff0c;表示复用功能IO&#xff0c;主要用于实现IO端口的复用功能以及外部中断的控制 STM32外设有很多I/O以及内置外设&#xff08;如12C&#xff0c;ADC,ISP,USART等&#xff09;。为节省引出管脚的…

案例分享:数据集市搭建方案中集成SQLFlow数据血缘分析工具

本文中描述的数据集市搭建方案是一家跨国公司在AWS平台上的具体实践案例。我公司参与其中的数据血缘部分的建设&#xff0c;SQLFlow数据血缘分析工具在该方案中帮助用户实现了数据血缘分析。 用户使用Redshift 数据库仓库进行数据集市开发。从各种数据源提取数据&#xff0c;并…

【电路笔记】-B类放大器

B类放大器 文章目录 B类放大器1、概述2、B类放大器介绍3、推挽式配置4、限制交叉失真5、B类放大器效率6、总结1、概述 我们在之前的文章中已经知道,A 类放大器的特点是导通角为 360,理论最大效率为 50%。 在本文中,我们将详细介绍另一类放大器,称为B类放大器,它是为解决A…

CAN总线Bus-off机制介绍及恢复策略说明

CAN总线Bus-off机制介绍及恢复策略说明 Bus-off产生机制 CAN通信Bus-off即总线关闭态,一个CAN节点有三种状态,主动错误状态、被动错误状态以及总线关闭态。如下图可知进入Bus-off的原因是因为发送错误大于255,在此状态节点不能收发报文。 以上三种错误状态标识发生故障的严…

让GNSSRTK不再难【第17讲 RTK定位技术原理-站间单差浮点解--第1部分】

第17讲 RTK定位技术原理-站间单差浮点解 RTK技术其实就是在RTD技术的基础上增加载波观测值的使用。由于伪距的误差在分米量级&#xff0c;即使我们通过站间单差消除掉绝大部分的伪距误差&#xff0c;但受限于伪距的精度&#xff0c;我们也只能达到分米量级的定位水平。 但载波…

【Vue】使用html、css实现鱼骨组件

文章目录 组件测试案例预览图 组件 <template><div class"context"><div class"top"><div class"label-context"><div class"label" v-for"(item, index) in value" :key"index">…

启动Nuxt-hub-starter: Failed to initialize wrangler bindings proxy write EOF

重新安装 node.js 这样做可以确保下载到了适合的 Windows 框架、Chocolatey&#xff08;一款Windows包管理工具&#xff09;、Python 等资源。 这个错误与Node版本、pnpm/yarn 的版本无关&#xff01; Node.js — Download Node.js (nodejs.org)

实证分析影响关系研究40+回归模型汇总整理

研究自变量X与因变量Y的影响关系时&#xff0c;回归模型是常用的方法。但是不同的回归模型其适用条件不同、种类繁多。SPSSAU目前提供了40多种不同的回归模型&#xff0c;如何选择适合的模型成为关键问题&#xff1b;此外&#xff0c;如何有效分析回归模型的结果也是研究中的重…

智能座舱相关问答

一、基本概念与理解 智能座舱的定义 回答&#xff1a;智能座舱是指在现代交通工具中&#xff0c;通过应用智能技术&#xff0c;实现对乘客座舱环境和服务进行智能化管理和优化的系统。它不仅提供更加舒适的乘坐体验&#xff0c;还能通过精确的数据分析和实时监控&#xff0c;提…

在Stimulsoft 报告中连接来自 MySQL 的数据

Stimulsoft Ultimate &#xff08;原Stimulsoft Reports.Ultimate&#xff09;是用于创建报表和仪表板的通用工具集。该产品包括用于WinForms、ASP.NET、.NET Core、JavaScript、WPF、PHP、Java和其他环境的完整工具集。无需比较产品功能&#xff0c;Stimulsoft Ultimate包含了…