前言
本文讲解表单搜索业务组件的封装,包括布局、搜索、重置和展开/收起。主要组件包括按钮组件 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搜索封装】。关注本栏目,会实时更新。