React后台管理(十一)-- 开发页面前准备 --- 表单搜索组件封装


前言

本文讲解表单搜索业务组件的封装,包括布局、搜索、重置和展开/收起。主要组件包括按钮组件 SearchButton、表单项组件 SearchItem 和表单盒子组件 SearchIndex。本系列以简单学习为主,后续会通过配置对象数组来生成表单项,而不需要每个表单项都单独编写 。


一、表单盒子组件 SearchIndex

源码+详细注释如下:

// @/components/search/index.jsx
import React, { useState, useImperativeHandle } from "react";
import { Form, Row } from "antd";
import "./index.scss";
const SearchIndex = (props) => {
  const [formLayout, setFormLayout] = useState("outline");
  const formItemLayout = {
    labelCol: {
      span: 0,
    },
    wrapperCol: {
      span: 24,
    },
  };
  const [form] = Form.useForm();
  const reset = () => {
    form.resetFields();
  };
  // 获取form表单参数值
  const getFieldValue = () => {
    return form.getFieldValue();
  };
  // 设置form表单某个字段值
  const setFieldValue = (field, value) => {
    form.setFieldsValue({
      [field]: value,
    });
  };
  // 暴露给父组件的方法放在这里
  useImperativeHandle(props?.searchRef, () => ({
    reset,
    getFieldValue,
    setFieldValue,
  }));
  return (
    <div className="search-container">
      <Form form={form} {...formItemLayout} layout={formLayout}>
        <Row gutter={16} style={{ width: "100%" }}>
          {props.children}
        </Row>
      </Form>
    </div>
  );
};

export default SearchIndex;
-------------------------------------------------------------------------------------------------------------------
// @/components/search/index.scss
.search-container {
  padding: 16px 16px 0;
  border-bottom: 16px solid #f5f5f5;
  background-color: #fff;
  .ant-form-item {
    margin-bottom: 16px !important;
  }
}

二、表单项组件 SearchItem

源码+详细注释如下:

// @/components/search/item.jsx
import React, { useMemo } from "react";
import { Form, Col } from "antd";
import "./item.scss";

const SearchItem = (props) => {
  // 设置label宽度
  const labelWidthStyle = useMemo(() => {
    return props.labelWidth ? { width: props.labelWidth } : {};
  }, [props.labelWidth]);
  return (
    <Col className="gutter-row" span={props?.span || 6}>
      <Form.Item name={props?.name}>
        <div className="search-item">
          {/* 渲染label */}
          <label style={labelWidthStyle}>{props?.label}</label>
          {/* 渲染子组件 */}
          <div>{props.children}</div>
        </div>
      </Form.Item>
    </Col>
  );
};
export default SearchItem;
-------------------------------------------------------------------------------------------------------------------
// @/components/search/item.scss
.search-item {
  display: flex;
  align-items: center;
  label {
    width: 70px;
  }
  > div {
    flex: 1;
    width: 0;
  }
}
.search-item-button {
  label {
    display: none;
  }
}


三、按钮组件 SearchButton

源码+详细注释如下:

// @/components/search/button.jsx
import React, { useState } from "react";
import { Space, Button } from "antd";
import { UpOutlined, DownOutlined } from "@ant-design/icons";
import useStore from "@/store";
const SearchButton = (props) => {
  const { TableStore } = useStore(); // 使用表格store
  const collapseStyle = { padding: "0 5px" }; // 设置展开收起样式
  const collapseMargin = { marginRight: "10px" }; // 设置展开收起样式
  const [open, setOpen] = useState(false); // 是否展开
  // 展开收起
  const toggleSearchItem = () => {
    setOpen(!open);
    props?.toggle(!open); // 传递展开收起事件给父组件
  };
  // 搜索
  const search = () => {
    TableStore.SET_FILTER_ACTION("search"); // 记录筛选动作
    props?.search(); // 传递搜索事件给父组件
  };
  // 重置
  const reset = () => {
    TableStore.SET_FILTER_ACTION("reset"); // 记录筛选动作
    props?.reset(); // 传递重置事件给父组件
  };
  return (
    <Space className="pull-right dis-flex">
      <Button type="primary" style={collapseMargin} onClick={() => search()}>
        查 询
      </Button>
      <Button style={collapseMargin} onClick={() => reset()}>
        重 置
      </Button>
      <Button type="link" style={collapseStyle} onClick={() => toggleSearchItem()}>
        {open ? "收起" : "展开"}
        {open ? <UpOutlined /> : <DownOutlined />}
      </Button>
    </Space>
  );
};

export default SearchButton;

四、页面使用方式

// 引用search相关组件
import SearchIndex from "@/components/search/index.jsx";
import SearchItem from "@/components/search/item.jsx";
import SearchButton from "@/components/search/button.jsx";
// html
<SearchIndex searchRef={searchRef}>
   <SearchItem label="客户名:" name="name" labelWidth="60px">
      <Input placeholder="请输入名称/简称" maxLength={100} />
   </SearchItem>
   <SearchItem label="联系人:" name="liaisonName" labelWidth="60px">
      <Input placeholder="请输入" maxLength={100} />
   </SearchItem>
   <SearchItem label="联系人手机:" name="liaisonMobile" labelWidth="90px">
      <Input placeholder="请输入" maxLength={20} />
   </SearchItem>
   {open ? (
      <SearchItem label="状态:" name="brandStatus" labelWidth="45px">
         <Select placeholder="请选择" options={statusOptions} onChange={onStatusChange} allowClear />
      </SearchItem>
                ) : null}
      <SearchItem span={open ? 24 : 6}>
         <SearchButton toggle={handlerToggle} reset={handlerReset} search={handlerSearch}></SearchButton>
      </SearchItem>
</SearchIndex>

五、效果展示

在这里插入图片描述


总结

下一篇讲【页面常用hook封装 — useSearch搜索封装】。关注本栏目,会实时更新。

  • 23
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值