April 30 总结
antd cascader 类型 和最大限制问题
export declare type SingleValueType = (string | number)[];
import {SingleValueType} from 'rc-cascader/lib/Cascader';
export type OptionType = Array<{
value?: string | number | null;
label: string | React.ReactNode;
children?: Array<{value?: string | number | null; label: string | React.ReactNode}>;
}>;
const handelChange = (val: SingleValueType, selectTion: OptionType) => {
const {region, regionCode} = covertParams(selectTion);
const regionConfig = {
region,
regionCode,
};
setCaster(val);
setKeys(regionConfig);
};
const cascaderChange = (code: SingleValueType[], selectedOptions: OptionType[]): void => {
console.warn('code', code, 'selectedOptions', selectedOptions);
if (selectedOptions.length > 5) {
const deleteArr = code.slice(0, 5);
form.setFieldsValue({region: deleteArr});
message.warn('超出最大数量,最多不超过5处', 1);
}
const {region, regionCode} = covertParams(selectedOptions.slice(0, 5));
console.warn('region-label', region, regionCode);
form.setFieldsValue({regionLabel: region});
};
const typeChange = (val: string | any, selectTion?: any) => {
if (Array.isArray(selectTion) && selectTion.length > 5) {
message.warn('超出最大数量,最多不超过5处', 1);
}
if (Array.isArray(selectTion) && (flag === SELECT || flag === DATA || flag === DOOR || flag === STATISTICS)) {
const {region, regionCode} = covertParams(selectTion.slice(0, 5));
region,
regionCode,
};
commonParams('typeKeywords', selectTion ? regionConfig : []);
}
const type = flag === DATA ? val : val.slice(0, 5);
setSearchData(state => {
return {
...state,
type,
};
});
};
状态维护在自定义hook中的组件,怎么让其他组件拿到实时的值
使用 forwardRef 和 useImperativeHandle 暴露顶部组件的最新值,
外部组件给这个组件传入 ref对象 , 使用 headerBar.current.sendSearch (暴露的方法)
就可以获得 header 组件最新的值。
值得注意的是,自定义hook只是逻辑复用,不是状态复用,
使用自定以hook的组件可以把最新的state传递出去。
过度复用组件、复用逻辑带来的复杂度问题
无论是组件复用还是逻辑复用,都是为了减少相同代码、降低耦合,
但过度组件封装、逻辑复用就会带来很复杂的判断问题,
像这样的组件或自定义hook,往往为了兼容不同组件的间的样式差别、或者是逻辑的区别,
往往要写很多的flag,
这就带来了多而杂的判断问题,
必须花时间去读。
这样一来虽然完成了ui、逻辑的抽离
但也使复杂度更高了。
怎么样书写更好、可读性和维护性更佳的组件、自定义hook是一个值得思考的问题。
写一个header 组件,她将会接收一些参数,
这些不同的text 将会被当做组件一个数组的title,
这个数组将被过滤,条件是title不为空的将被保留 。
========================================
自定义hook useHeaderBar 将负责维护header 组件的状态,
const {
searchData, contentChange, typeChange, statusChange, timeChange, handelSearch, handelReset, namerChange
} = useHeaderBar(flag);
这些不同的函数将被分配给不同的组件,
在值变化时,useHeaderBar 中的这些函数将更新 她维护的 state 对象,
这个对象是整个header 组件 input 、select ... 和其他组件的state集合,
这个state 也同样会给到header 组件,
header 组件使用这个 state[key]的方式赋予 input 或是其他组件的value ,
来完成双向数据绑定,
这真的很像 antd 中 useForm 表单域的操作 (也可能不像)。
--------------------------
不同的使用 header 组件的组件,需要传入flag ,
用这个 flag 来区分 不同组件中的搜索和重置。
注意: 我们在搜索的函数中,
使用了同步函数,
该函数的作用是能够获取useState 改变后的最新值,
搜索函数本身使用这个同步函数或许是多此一举,
但在 reset 函数中,刚刚重置完state,
再次调用搜索函数,
我们就能用得上了。
setState return 一个值
如果新的 state 需要通过使用先前的 state 计算得出,那么可以将函数传递给 setState。该函数将接收先前的 state,并返回一个更新后的值。
这种 也叫做 函数式更新
Antd Cascader 配合 china-division 插件或json文件的省市区级联
import provinces from 'china-division/dist/provinces.json';
import cities from 'china-division/dist/cities.json';
import areas from 'china-division/dist/areas.json';
const chinaDiviSion = () => {
areas.forEach((area: any) => {
const matchCity = cities.filter((city: any) => city.code === area.cityCode)[0];
if (matchCity) {
matchCity.children = matchCity.children || [];
matchCity.children.push({
label: area.name,
value: area.code,
});
}
});
cities.forEach(city => {
const matchProvince = provinces.filter(province => province.code === city.provinceCode)[0];
if (matchProvince) {
matchProvince.children = matchProvince.children || [];
matchProvince.children.push({
label: city.name,
value: city.code,
children: city.children,
});
}
});
const options = provinces.map(province => ({
label: province.name,
value: province.code,
children: province.children,
}));
return options;
};
export default chinaDiviSion;
import pccode from '@/utils/pccode.json';
const chinaDiviSion = () => {
const options = pccode.map((item: any) => {
const children = item.children?.map((ele: any) => ({
label: ele.name,
value: ele.code,
}));
if (!item.children) {
return {
label: item.name,
value: item.code,
};
}
return {
label: item.name,
value: item.code,
children: children,
};
});
return options;
};
export default chinaDiviSion;