Styled Components不传递DOM属性:disabled属性未渲染到按钮DOM元素
问题根因
- 类型定义错误:所有按钮相关的props接口错误继承了通用
React.HTMLAttributes,该类型不包含disabled等button元素专属的原生属性,导致styled-components将disabled识别为自定义属性过滤,没有传递到DOM上。 - 属性透传遗漏:Button组件没有接收并透传父组件传入的其余原生button属性,导致
type等属性丢失。 - 禁用态交互缺失:样式未对禁用状态做交互拦截,即使DOM有disabled属性,也可能出现异常可点击的问题。
修复方案
1. 修改Button.style.ts
将StyledButtonProps的继承改为React.ButtonHTMLAttributes<HTMLButtonElement>,同时补充禁用态样式:
import styled from 'styled-components'; import { fontFamily, fontSize, fontWeight, getSpacing } from '../../stylesheet'; // 改为继承ButtonHTMLAttributes interface StyledButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> { fullWidth?: boolean; backgroundColor: string; textColor: string; borderColor?: string; borderRadiusProp: string; } export const StyledButton = styled.button<StyledButtonProps>(props => ({ cursor: props.disabled ? 'not-allowed' : 'pointer', height: '45px', borderRadius: props.borderRadiusProp, ...((props.fullWidth ?? false) && { width: '100%', }), padding: '12px 24px', color: props.textColor, background: props.backgroundColor, textAlign: 'center', // 禁用态加pointer-events拦截点击 ...(props.disabled && { pointerEvents: 'none' }), ...(props.borderColor ?? '' ? { borderWidth: 1, borderColor: props.borderColor, } : { border: 'none', }), // 非禁用态才生效hover样式 ...(!props.disabled && { ':hover': { backgroundColor: props.backgroundColor, } }) })); export const ButtonContent = styled.div` height: 100%; display: flex; flex-direction: row; align-items: center; justify-content: center; font-family: ${fontFamily.main}; font-size: ${fontSize.medium}; font-weight: ${fontWeight.large}; margin-right: ${getSpacing(4)}; margin-left: ${getSpacing(4)}; `;
2. 修改Button.tsx
将ButtonProps的继承改为React.ButtonHTMLAttributes<HTMLButtonElement>,同时补充剩余属性透传:
import React from 'react'; import { borderRadius } from 'stylesheet'; import { ButtonContent, StyledButton } from './Button.style'; // 改为继承ButtonHTMLAttributes export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> { fullWidth?: boolean; borderRadiusProp?: string; backgroundColor: string; textColor: string; borderColor?: string; children: React.ReactNode; } const Button = ({ onClick, fullWidth, borderRadiusProp = borderRadius.m, backgroundColor, textColor, borderColor, disabled = false, children, // 新增接收剩余属性 ...rest }: ButtonProps): JSX.Element => { return ( <StyledButton disabled={disabled} onClick={onClick} fullWidth={fullWidth} borderColor={borderColor} borderRadiusProp={borderRadiusProp} backgroundColor={backgroundColor} textColor={textColor} // 透传剩余属性 {...rest} > <ButtonContent>{children}</ButtonContent> </StyledButton> ); }; export default Button;
3. (可选)修改GradientButton.tsx的类型继承
将GradientButtonProps的继承改为React.ButtonHTMLAttributes<HTMLButtonElement>,保持类型一致性:
// 改为继承ButtonHTMLAttributes interface GradientButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> { fullWidth?: boolean; children: React.ReactNode; disabled?: boolean; gradient?: keyof typeof gradientColors; }
修复后disabled属性会正常传递到原生button DOM上,原生按钮默认会拦截点击事件,加上样式里的pointer-events: none双重保障,不会再出现禁用后仍可点击的问题。
内容的提问来源于stack exchange,提问作者JustinMartinDev
相关产品推荐
相关产品推荐

