前言
因为公司最近重构PC端业务,其中大部分业务逻辑相似,页面头部都有一个搜索栏,但搜素条件不尽相似,于是封装一个公共组件就十分有必要;
由于是react新手,在踩了新手足够的坑后,利用最近的一些积累,封装了一个
结合antd、immer、reactHooks编写的一个简单但实用的搜索栏组件
代码
由于搜索栏用到的组件类型有input、select、picker等多种多样,于是利用react的函数式编程思想,通过遍历类型生成对应的组件类型能够省下大量的代码以及时间;
下面是抽离了两个比较常用的类型后的搜素栏组件:
import React, { useState, useEffect } from "react";
import { Button, Select, Input, message } from "antd";
import { produce } from "immer";
/**
* useEffect(event,[state]) => 处理副作用
* 相当于modlels里的subscriptions,
* 传递给它的函数将会在组件渲染到屏幕后运行。
* 参数:
* event:状态改变执行的函数
* [state]:event函数执行时机的依赖,只要数组里面依赖的state改变才会执行event
*/
import { speciaTextPattern } from "@/models/globalData";
import styleSearch from "@/styles/main_search.less";
const { Option } = Select;
const SearchLineComponent = props => {
let { searchList } = props;
if (!searchList) {
searchList = [];
}
const [canSearch, setCanSearch] = useState(true);
const [stateList, setStateList] = useState([...searchList]);
/** 搜索 */
const handleSearch = () => {
if (!canSearch) {
message.destroy();
message.error("请检索搜索条件是否符合条件");
return;
}
let values = {};
stateList.map(_state => {
values = produce(values, draftValues => {
draftValues[_state.key] = _state.value;
});
return values;
});
console.log(values);
props.onSearch(values);
};
/** 校验 */
const handlePattern = (e, text, isError = false) => {
if (e.target.value.length > 0 && !speciaTextPattern.test(e.target.value)) {
message.destroy();
message.error(text);
props.stopPagination(true);//关联了Table组件的分页器,用以阻止分页器可以点击
setCanSearch(false);
} else {
props.stopPagination(false);
setCanSearch(true);
}
};
/** 输入框失去焦点-触发校验 */
const handleInputBlur = (e, item) => {
handlePattern(e, `请正确输入查询${item.label}`, true);
};
/** 设置搜素Item对应的值 */
const handleSetState = (val, item) => {
let arr = [...stateList];
arr = arr.map(_state => {
if (_state.key === item.key) {
_state = produce(_state, draftState => {
draftState.value = val;
});
}
return _state;
});
setStateList(arr);
};
/** 输入框 */
const handleInputChange = (e, item) => {
handlePattern(e, `请正确输入查询${item.label}`);
const val = e.target.value.trim();
handleSetState(val, item);
};
/** 下拉选择 */
const handleSelectChange = (val, item) => {
handleSetState(val, item);
if (props.isSelectSearch) {
/** 下拉搜素-全部 */
handleSearch();
return;
}
if (props.onSelect) {
/** 下拉搜素-当前item */
props.onSelect({
[item.key]: val
});
}
};
return (
<div className={styleSearch.search}>
{searchList.length > 0 &&
searchList.map((form, idx) => {
return (
<React.Fragment key={form.key + idx}>
{form.type === "input" && (
<div className={styleSearch["flex-item"]}>
<span className={styleSearch["label-100"]}>
{form.label}:
</span>
<Input
allowClear
size="default"
type="text"
maxLength={8}
defaultValue={form.defaultValue}
className={`${styleSearch["search-select"]}`}
placeholder={form.placeholder}
onPressEnter={() => handleSearch()}
onBlur={e => handleInputBlur(e, form)}
onChange={e => handleInputChange(e, form)}
/>
</div>
)}
{form.type === "select" && (
<div className={styleSearch["flex-item"]}>
<span className={styleSearch["label-100"]}>
{form.label}:
</span>
<Select
allowClear
className={`${styleSearch["search-select"]} ${
styleSearch["search-type"]
}`}
defaultValue={form.defaultValue}
placeholder={form.placeholder}
onChange={e => handleSelectChange(e, form)}
>
{form.selectList.map((cl, idx) => {
return (
<Option key={cl.id} value={cl.id}>
{cl.name}
</Option>
);
})}
</Select>
</div>
)}
</React.Fragment>
);
})}
<Button
style={{ marginLeft: "15px" }}
className={styleSearch.add}
onClick={handleSearch}
type="primary"
>
查询
</Button>
</div>
);
};
SearchLineComponent.propTypes = {};
export default SearchLineComponent;
使用
import {
SearchLineComponent
} from "@/components";
const searchList = [
{
type: "select",
key: "level",
label: "预警等级",
value: undefined,
placeholder: "请选择",
selectList: [
{
id: 0,
name: "A级"
},
{
id: 1,
name: "B级"
}
]
},
{
type: "select",
key: "reason",
label: "加黑原因",
value: undefined,
placeholder: "请选择",
selectList: [
{
id: 0,
name: "A级"
},
{
id: 1,
name: "B级"
}
]
},
{
type: "input",
key: "name",
label: "姓名",
placeholder: "请输入姓名",
value: undefined
}
];
...
state={
searchList
}
...
render(){
const {searchList} = this.state;
return (
<React.Fragment>
// ...
{/* 搜索栏 */}
<SearchLineComponent
// isSelectSearch // 优先级比onSelect高
onSelect={val => this.handleSelectSearch(val)}
onSearch={values => this.handleSearch(values)}
stopPagination={val => this.handleStopPagination(val)}
searchList={searchList}
> </SearchLineComponent>
</React.Fragment>
)
}
网友评论