当前位置: 首页 > ai >正文

HOW - 基于组件库组件改造成自定义组件基本规范

文章目录

  • Select 选择器改造
    • 1. 明确组件目标
    • 2. 定义组件 API
    • 3. 合理使用默认值
    • 4. 支持类型安全的 options 传递
    • 5. 支持 ForwardRef(可选)
    • 6. 封装样式(可选)
    • 7. 使用示例
  • ...props 位置
    • 推荐顺序:最后
    • 原因:
    • 简要总结
  • 合并内外部逻辑
    • 场景示例:处理 onChange
    • 方案一:手动合并函数或属性
    • 方案二:兼顾默认值 + 用户自定义
    • 总结:封装时处理逻辑建议
    • 最佳实践示例组件
  • 更安全的方式

Select 选择器改造

比如,要将 Ant Design 的 Select 组件封装成你的 CustomSelect 组件并规范化封装,建议遵循以下几个方面的最佳实践:

1. 明确组件目标

你可以定义这个 CustomSelect 的目标,例如:

  • 更统一的样式
  • 集成默认功能(比如加载状态、本地搜索等)
  • 简化使用(比如默认占位符、默认事件处理)

2. 定义组件 API

设计你自己的 CustomSelect 组件的 props 类型时,建议基于 antd 的 SelectProps 做扩展:

// CustomSelect.tsx
import React from 'react';
import { Select, SelectProps } from 'antd';export interface CustomSelectProps extends SelectProps {label?: string; // 可选,封装 labelwrapperClassName?: string; // 可选,外层 class
}const CustomSelect: React.FC<CustomSelectProps> = ({label,wrapperClassName,...props
}) => {return (<div className={wrapperClassName}>{label && <label className="block mb-1 text-gray-700">{label}</label>}<Select {...props} /></div>);
};export default CustomSelect;

3. 合理使用默认值

在封装中添加默认值可以提升使用体验:

<SelectshowSearchallowClearplaceholder="请选择"optionFilterProp="label"filterOption={(input, option) =>(option?.label ?? '').toLowerCase().includes(input.toLowerCase())}{...props}
/>

你可以在 CustomSelect 内设置 showSearchallowClearfilterOption 等默认行为。

4. 支持类型安全的 options 传递

你可以加一个 options 支持(类型为 DefaultOptionType[]):

import type { DefaultOptionType } from 'antd/es/select';interface CustomSelectProps extends SelectProps {options?: DefaultOptionType[];
}

并配合传入:

<Selectoptions={props.options}{...otherProps}
/>

5. 支持 ForwardRef(可选)

如果你希望外部能访问内部 ref,可以使用 forwardRef

const CustomSelect = React.forwardRef<any, CustomSelectProps>((props, ref) => {return <Select ref={ref} {...props} />;
});

6. 封装样式(可选)

统一样式可以放在 CustomSelect.module.css 或用 tailwind 写死样式:

<Select className="w-full rounded-md" />

7. 使用示例

<CustomSelectlabel="城市"value={selectedCity}onChange={setSelectedCity}options={[{ label: '北京', value: 'beijing' },{ label: '上海', value: 'shanghai' }]}
/>

…props 位置

{...props} 应该放在 最后面

推荐顺序:最后

<SelectshowSearchallowClearplaceholder="请选择"{...props}
/>

原因:

  1. 避免被覆盖
    如果你把 ...props 放在前面,后面设置的属性会覆盖它,导致用户传入的属性失效。

    // 错误示例(可能导致用户传入的属性无效)
    <Select{...props}showSearch={false}  // 会覆盖 props.showSearch,即使用户传了 true
    />
    
  2. 正确示例:用户可以覆盖默认行为

    <SelectshowSearchallowClearplaceholder="请选择"{...props}  // 用户传入的值会覆盖上面的默认值
    />
    

    例如用户传入 allowClear={false},最终就会生效。

简要总结

放置位置是否推荐原因说明
最后面✅ 推荐用户传入值可覆盖默认值
最前面❌ 不推荐默认值会覆盖用户传入值,造成困惑

如果你还封装了内部逻辑(比如 onChange 的包裹处理),那可以手动合并它,而不是直接写在默认值中。

合并内外部逻辑

如果你希望在自定义组件中:

内部自定义属性可以“加工”后使用
同时仍 兼容外部传进来的属性,即可以被用户覆写/增强

场景示例:处理 onChange

我们以 onChange 为例,如果你想在组件内部处理一些逻辑后再执行用户传入的 onChange,做法如下:

方案一:手动合并函数或属性

const handleChange = (value: any, option: any) => {// 自定义逻辑,比如打日志console.log('[CustomSelect] selected:', value);// 调用外部传入的 onChange(如果有)props.onChange?.(value, option);
};<SelectshowSearchallowClearplaceholder="请选择"{...props}onnChange={handleChange}
/>

方案二:兼顾默认值 + 用户自定义

例如:

<SelectshowSearch={props.showSearch ?? true} // 外部可以传 false,否则默认 trueallowClear={props.allowClear ?? true}placeholder={props.placeholder ?? '请选择'}{...props}
/>

这样可以兼顾默认值 + 用户自定义。

总结:封装时处理逻辑建议

类型写法是否允许外部覆盖
函数型属性主动调用外部函数(如 onChange)✅ 推荐
布尔/字符串属性使用 ?? 提供默认值✅ 推荐

最佳实践示例组件

export const CustomSelect: React.FC<CustomSelectProps> = ({label,wrapperClassName,onChange,...props
}) => {const handleChange = (value: any, option: any) => {// 内部逻辑console.log('[CustomSelect] selected:', value);// 外部逻辑onChange?.(value, option);};return (<div className={wrapperClassName}>{label && <label className="block mb-1 text-gray-700">{label}</label>}<SelectshowSearch={props.showSearch ?? true}allowClear={props.allowClear ?? true}placeholder={props.placeholder ?? '请选择'}{...props}onChange={handleChange}/></div>);
};

更安全的方式

更安全的方式是明确列出你需要的 props,而不是使用 {...props}

  const handleChange = (value: any, option: any) => {// 内部逻辑console.log('[CustomSelect] selected:', value);// 外部逻辑onChange?.(value, option);};<SelectshowSearchallowClearplaceholder="请选择"onChange={handleChange}// 明确列出其他需要的 propsstyle={props.style}className={props.className}// 其他需要的 props...
/>

即建议不要偷懒,直接使用 ...props,而是使用什么传入什么。并且可以参考 onChagne 一样合并内外部逻辑。

http://www.xdnf.cn/news/8273.html

相关文章:

  • JavaScript- 1.6 基本控制流
  • 【瑞数3代】药监评审中心逆向分析 | 后缀MmEwMD参数
  • 采用多维计算策略(分子动力学模拟+机器学习),显著提升 α-半乳糖苷酶热稳定性
  • ArcGIS Pro 3.4 二次开发 - 地理数据库
  • Java多线程同步:确保并发安全的关键策略
  • Redis删除策略
  • gitlab占用内存 优化
  • UE5 keyboard A这类键盘输入事件没有响应
  • redis 缓存穿透,缓存雪崩,缓存击穿
  • 【前端】Bun:快速上手
  • 【ubuntu】安装NVIDIA Container Toolkit
  • 什么是 AWS Migration Evaluator?
  • Apache ZooKeeper原理与应用
  • ReAct 与 CoAct:AI 代理的推理与行动之旅
  • 【三维重建】【3DGS系列】【深度学习】3DGS的理论基础知识之协方差矩阵控制椭球
  • 「短剧系统开发」定制化技术架构|高并发微服务 + AI 推荐,快速搭建流量级短剧平台
  • JDBC-java操作数据库
  • k8s网络架构
  • 养生指南:五维焕新健康生活
  • SQL 的 DECODE 函数
  • 会话管理有哪些
  • 蓝桥杯国14 不完整的算式
  • 中文域名25周年,取得哪些里程碑式的进展?
  • 力扣HOT100之图论:207. 课程表
  • MQSQL笔记二——非操控数据操作
  • 【Python】Python 装饰器的用法总结
  • 聚铭安全管家平台2.0重磅发布——大模型智驱高效降本新方向
  • 基于OpenLCA、GREET、R语言的生命周期评价方法、模型构建及典型案例应用
  • LVGL(lv_span富文本控件)
  • Ubuntu 25.04 锁屏不能远程连接的解决方案