April30总结


April 30 总结

antd cascader 类型 和最大限制问题
// antd Cascader 的 onChange

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);
};

// 多选 区别在于 多选是二维数组

// Cascader maxTagCount 属性无效,这里手动限制最大值

// code 用来双向数据绑定,selectedOptions 是具体的这一项地区的中文和地区码item

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);
        // return;
    }
    const {region, regionCode} = covertParams(selectedOptions.slice(0, 5));
    console.warn('region-label', region, regionCode);
    form.setFieldsValue({regionLabel: region});
};
// useHeaderBar.ts

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是一个值得思考的问题。
headerBar 组件复用与逻辑复用
写一个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文件的省市区级联
// 使用 china-division 插件
import provinces from 'china-division/dist/provinces.json';
import cities from 'china-division/dist/cities.json';
import areas from 'china-division/dist/areas.json';

// 转换key
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;
// 使用json文件

// 使用:

// 给到 Cascader 的 options 属性 chinaDiviSion()

// 若 json 文件 的 key 已经是 value 和 label children? ,直接将 引入的json 变量给到 Cascader即可

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;

文章作者: KarlFranz
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 reprint policy. If reproduced, please indicate source KarlFranz !
评论
  目录