项目场景:
例如:下拉框需要调后台接口,antd基础的下拉列表无法满足多样化需求。
在Antd基础下拉框进行封装
首先父组件中的changeForm
可以根据键名,来更改键值是一种兼容写法,同样适用在input、radio
等组件中。
Proc子组件,这里我是自己写了默认值,来渲染生成的getOptions,实际项目中可以根据传来的url,在useEffect中进行调接口,并接口在请求中设置为loading做一下小优化。url参数这里我没有写,实际项目中可以自行封装。
默认值中,给每一项添加了uid
,这里是防止列表中label或value是相同的,点击选择时可能会有bug。选择值时,handleChange中的v是uid的值
,通过uid来判断点击的列表中的哪一项。handleChange中 let val = opts.find(( r ) => r["uid"] == v);
获取的具体的某一项,例如:uid:1,那么val={ labels: “leb1”, values: “111”, uid: 1 },是es6的find用法。
父组件:
import React, { memo, useEffect, useState, useCallback } from "react";
import Proc from "../Proc"; //引入子组件
export default memo(() => {
const [form, setForm] = useState({});
const changeForm = useCallback(
(fileName) => {
return (v) => {
form[fileName] = v;
setForm(Object.assign({}, form));
};
},
[form]
);
return (
<div>
<h1>下拉组件封装</h1>
<Proc
labelKey="labels"
label={form.selL}
value={form.valueL}
changeForm={{ labels: changeForm("labKey"), values: changeForm("valueKey") }}
/>
</div>
);
});
子组件:
import React, { memo, useEffect, useMemo } from "react";
import { Select } from "antd";
const Option = Select.Option;
export default memo(({ labelKey, valueKey, label, value, changeForm }) => {
useEffect(()=>{
// 如果下拉框需要回显数据,可以使用传来的 label, value 在opts中进行对应,取到uid值后,设置defaultValue
},[])
const opts = useMemo(() => {
return [
{ labels: "leb1", values: "111", uid: 1 },
{ labels: "leb2", values: "222", uid: 2 },
{ labels: "leb3", values: "333", uid: 3 },
{ labels: "leb4", values: "444", uid: 4 }
];
}, []);
const handleChange = (v) => {
// 这边changeForm为对象 keys打印出为 ['labels']
let keys = Object.keys(changeForm);
keys.forEach((item) => {
let val = opts.find((r) => r["uid"] == v);
changeForm[item](val[item]);
});
};
const getOptions = () => {
return opts.map((item, index) => {
return (
<Option value={item["uid"]} key={item.uid}>
{/* 这边显示需要展示label,选中的值为设置的id值 */}
{item[labelKey]}
</Option>
);
});
};
return (
<div>
<Select defaultValue={4} style={{ width: 120 }} onChange={handleChange}>
{getOptions()}
</Select>
</div>
);
});
效果如下