前言:在我们的日常开发包括日常开发中,经常与button打交道,在一个组件库中,Button组件也是最易开发的一个。
仓库地址:
https://gitee.com/cquptzsn/fun-ui
需求分析:
一、首先,定义按钮的一些属性:
ButtonType-按钮类型:
使用枚举:
export enum ButtonType {
Primary = 'primary',
Default = 'default',
Danger = 'danger',
Link = 'link'
}
ButtonSize-按钮大小:
export enum ButtonSize {
Large = 'lg',
Small = 'sm'
}
二、通过classNames给不同的属性设置不同的类名从而设置不同样式
const classes = classNames('btn', className, {
[`btn-${btnType}`]: btnType,
[`btn-${size}`]: size,
'disabled': (btnType === ButtonType.Link) && disabled
})
*三、为了使我们封装的Button 组件能有原生 button 和 a标签 的属性,需要把我们自定义的props 和 button , a 原生的属性结合
自定义的属性:
使用 typescript 获取原生属性提示和自定义属性结合:
button: type NativeButtonProps = BaseButtonProps & React.ButtonHTMLAttributes
a: type AnchorButtonProps = BaseButtonProps & React.AnchorHTMLAttributes
将这两个属性结合并设置可选, 这里使用 typescript 的 Partial<>
export type ButtonProps = Partial<NativeButtonProps & AnchorButtonProps> //使用 Partial<> 使两种属性可选
通过以上步骤,我们封装的 Button 组件能够获取原生 button 和 a 的相关属性
四、不同标签设置返回不同内容
五、使用
要先导入
之后,我们给不同的类名设置不同样式即可
总代码:
import React from 'react';
import classNames from 'classnames'
export enum ButtonSize {
Large = 'lg',
Small = 'sm'
}
export enum ButtonType {
Primary = 'primary',
Default = 'default',
Danger = 'danger',
Link = 'link'
}
interface BaseButtonProps {
className?: string;
disabled?: boolean;
size?: ButtonSize;
btnType?: ButtonType;
children: React.ReactNode;
href?: string;
}
type NativeButtonProps = BaseButtonProps & React.ButtonHTMLAttributes<HTMLButtonElement> // 使用 交叉类型(&) 获得我们自己定义的属性和原生 button 的属性
type AnchorButtonProps = BaseButtonProps & React.AnchorHTMLAttributes<HTMLAnchorElement> // 使用 交叉类型(&) 获得我们自己定义的属性和原生 a标签 的属性
export type ButtonProps = Partial<NativeButtonProps & AnchorButtonProps> //使用 Partial<> 使两种属性可选
const Button: React.FC<ButtonProps> = (props) => {
const {
disabled,
className,
size,
btnType,
children,
href,
...restProps
} = props;
const classes = classNames('btn', className, {
[`btn-${btnType}`]: btnType,
[`btn-${size}`]: size,
'disabled': (btnType === ButtonType.Link) && disabled // 只有 a 标签才有 disabled 类名,button没有
})
if(btnType === ButtonType.Link && href) {
return (
<a
className={classes}
href={href}
{...restProps}
>
{children}
</a>
)
} else {
return (
<button
className={classes}
disabled={disabled} // button元素默认有disabled属性,所以即便没给他设置样式也会和普通button有一定区别
{...restProps}
>
{children}
</button>
)
}
}
Button.defaultProps = {
disabled: false,
btnType: ButtonType.Default
}
export default Button;
最后: 这里我只做了一些基本的类型,感兴趣可以自己再添加,样式文件我就不发出来了
网友评论