searchForm自适应布局 + 按钮插槽

发布于:2024-07-10 ⋅ 阅读:(153) ⋅ 点赞:(0)

收起

在这里插入图片描述

展开

在这里插入图片描述

代码:

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;