样式继承 #
一、样式继承基础 #
1.1 继承 HTML 元素 #
使用 styled(HTMLElement) 创建基础样式:
jsx
import styled from 'styled-components';
const Button = styled.button`
padding: 12px 24px;
font-size: 16px;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s;
`;
const PrimaryButton = styled(Button)`
background: #667eea;
color: white;
border: none;
&:hover {
background: #5a6fd6;
}
`;
const SecondaryButton = styled(Button)`
background: transparent;
color: #667eea;
border: 2px solid #667eea;
&:hover {
background: #667eea;
color: white;
}
`;
1.2 继承流程 #
text
样式继承链
┌─────────────────────────────────────────────────────────────┐
│ │
│ styled.button │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────┐ │
│ │ padding: 12px 24px │ │
│ │ font-size: 16px │ │
│ │ border-radius: 8px │ │
│ └─────────────────────────────────────┘ │
│ │ │
│ ▼ styled(Button) │
│ ┌─────────────────────────────────────┐ │
│ │ 继承基础样式 │ │
│ │ + background: #667eea │ │
│ │ + color: white │ │
│ │ + border: none │ │
│ └─────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
二、继承 React 组件 #
2.1 继承第三方组件 #
jsx
import styled from 'styled-components';
import { Link } from 'react-router-dom';
import { Button as MuiButton } from '@mui/material';
const StyledLink = styled(Link)`
text-decoration: none;
color: #667eea;
font-weight: 600;
padding: 8px 16px;
border-radius: 4px;
transition: background 0.2s;
&:hover {
background: rgba(102, 126, 234, 0.1);
}
`;
const CustomButton = styled(MuiButton)`
text-transform: none;
font-weight: 600;
border-radius: 8px;
`;
2.2 继承自定义组件 #
jsx
import styled from 'styled-components';
const BaseCard = styled.div`
background: white;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
padding: 24px;
`;
const ProductCard = styled(BaseCard)`
display: flex;
flex-direction: column;
gap: 16px;
img {
width: 100%;
height: 200px;
object-fit: cover;
border-radius: 8px;
}
`;
const UserCard = styled(BaseCard)`
display: flex;
align-items: center;
gap: 16px;
img {
width: 64px;
height: 64px;
border-radius: 50%;
}
`;
2.3 继承条件 #
被继承的组件必须接受 className prop:
jsx
import styled from 'styled-components';
function CustomComponent({ className, children }) {
return (
<div className={className}>
{children}
</div>
);
}
const StyledCustom = styled(CustomComponent)`
padding: 24px;
background: #f5f5f5;
`;
三、样式覆盖 #
3.1 覆盖继承的样式 #
jsx
const Button = styled.button`
padding: 12px 24px;
background: #667eea;
color: white;
border-radius: 8px;
`;
const RoundedButton = styled(Button)`
border-radius: 50px;
padding: 16px 32px;
`;
const OutlineButton = styled(Button)`
background: transparent;
color: #667eea;
border: 2px solid #667eea;
&:hover {
background: #667eea;
color: white;
}
`;
3.2 使用 !important(谨慎使用) #
jsx
const ImportantButton = styled(Button)`
background: #ff4d4f !important;
color: white !important;
`;
3.3 增强样式优先级 #
jsx
const Button = styled.button`
padding: 12px 24px;
background: #667eea;
color: white;
`;
const EnhancedButton = styled(Button)`
&& {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
`;
四、样式扩展 #
4.1 添加新样式 #
jsx
const Card = styled.div`
background: white;
border-radius: 12px;
padding: 24px;
`;
const InteractiveCard = styled(Card)`
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
&:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
}
`;
const AnimatedCard = styled(InteractiveCard)`
animation: fadeIn 0.3s ease;
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
`;
4.2 条件扩展 #
jsx
const Button = styled.button`
padding: 12px 24px;
border-radius: 8px;
font-size: 16px;
`;
const VariantButton = styled(Button)`
${props => props.variant === 'primary' && `
background: #667eea;
color: white;
border: none;
`}
${props => props.variant === 'secondary' && `
background: transparent;
color: #667eea;
border: 2px solid #667eea;
`}
${props => props.variant === 'danger' && `
background: #ff4d4f;
color: white;
border: none;
`}
`;
4.3 组合扩展 #
jsx
import styled, { css } from 'styled-components';
const basePadding = css`
padding: 16px;
`;
const baseBorder = css`
border: 1px solid #e0e0e0;
border-radius: 8px;
`;
const baseShadow = css`
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
`;
const Card = styled.div`
${basePadding}
${baseBorder}
${baseShadow}
background: white;
`;
const ElevatedCard = styled(Card)`
${baseShadow}
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
transform: translateY(-4px);
`;
五、多级继承 #
5.1 继承链 #
jsx
const Element = styled.button`
font-family: inherit;
font-size: 16px;
`;
const Button = styled(Element)`
padding: 12px 24px;
border-radius: 8px;
cursor: pointer;
border: none;
`;
const PrimaryButton = styled(Button)`
background: #667eea;
color: white;
&:hover {
background: #5a6fd6;
}
`;
const LargePrimaryButton = styled(PrimaryButton)`
padding: 16px 32px;
font-size: 18px;
`;
5.2 继承深度控制 #
jsx
const Base = styled.div`
padding: 16px;
`;
const Level1 = styled(Base)`
background: #f0f0f0;
`;
const Level2 = styled(Level1)`
border-radius: 8px;
`;
const Level3 = styled(Level2)`
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
`;
const Level4 = styled(Level3)`
border: 1px solid #e0e0e0;
`;
六、混合继承 #
6.1 使用 css 函数 #
jsx
import styled, { css } from 'styled-components';
const flexCenter = css`
display: flex;
align-items: center;
justify-content: center;
`;
const cardBase = css`
background: white;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
`;
const Card = styled.div`
${cardBase}
padding: 24px;
`;
const FlexCard = styled.div`
${cardBase}
${flexCenter}
min-height: 200px;
`;
6.2 条件混合 #
jsx
import styled, { css } from 'styled-components';
const elevated = css`
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
transform: translateY(-4px);
`;
const rounded = css`
border-radius: 16px;
`;
const bordered = css`
border: 2px solid #667eea;
`;
const Card = styled.div`
padding: 24px;
background: white;
border-radius: 8px;
${props => props.elevated && elevated}
${props => props.rounded && rounded}
${props => props.bordered && bordered}
`;
function App() {
return (
<>
<Card elevated rounded>Elevated & Rounded</Card>
<Card bordered>Bordered</Card>
<Card elevated rounded bordered>All styles</Card>
</>
);
}
6.3 样式组合函数 #
jsx
import styled, { css } from 'styled-components';
const withPadding = (size = 'md') => css`
padding: ${size === 'sm' ? '8px' : size === 'lg' ? '24px' : '16px'};
`;
const withMargin = (size = 'md') => css`
margin: ${size === 'sm' ? '4px' : size === 'lg' ? '16px' : '8px'};
`;
const withShadow = (level = 'low') => css`
box-shadow: ${level === 'high'
? '0 8px 24px rgba(0, 0, 0, 0.15)'
: '0 2px 8px rgba(0, 0, 0, 0.1)'};
`;
const Box = styled.div`
${props => withPadding(props.p)}
${props => withMargin(props.m)}
${props => withShadow(props.shadow)}
background: white;
border-radius: 8px;
`;
function App() {
return (
<>
<Box p="lg" m="md" shadow="high">Large padding, medium margin, high shadow</Box>
<Box p="sm" m="lg" shadow="low">Small padding, large margin, low shadow</Box>
</>
);
}
七、Props 继承 #
7.1 继承 Props 类型 #
tsx
import styled from 'styled-components';
interface ButtonProps {
$primary?: boolean;
$size?: 'small' | 'medium' | 'large';
}
const Button = styled.button<ButtonProps>`
padding: ${props =>
props.$size === 'small' ? '8px 16px' :
props.$size === 'large' ? '16px 32px' :
'12px 24px'
};
background: ${props => props.$primary ? '#667eea' : '#fff'};
color: ${props => props.$primary ? '#fff' : '#667eea'};
`;
const PrimaryButton = styled(Button)`
border: none;
font-weight: 600;
`;
const LargePrimaryButton = styled(PrimaryButton)`
font-size: 18px;
`;
7.2 扩展 Props #
tsx
import styled from 'styled-components';
interface BaseCardProps {
$elevated?: boolean;
}
interface ProductCardProps extends BaseCardProps {
$inStock?: boolean;
}
const BaseCard = styled.div<BaseCardProps>`
padding: 24px;
background: white;
border-radius: 12px;
box-shadow: ${props => props.$elevated && '0 8px 24px rgba(0, 0, 0, 0.15)'};
`;
const ProductCard = styled(BaseCard)<ProductCardProps>`
border: ${props => props.$inStock ? '2px solid #52c41a' : '2px solid #ff4d4f'};
`;
八、组件包装模式 #
8.1 包装器模式 #
jsx
import styled from 'styled-components';
const withCard = (Component) => styled(Component)`
padding: 24px;
background: white;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
`;
const Content = styled.div`
color: #333;
`;
const CardContent = withCard(Content);
function App() {
return (
<CardContent>
This content is wrapped in a card.
</CardContent>
);
}
8.2 高阶组件模式 #
jsx
import styled from 'styled-components';
function withStyledWrapper(styles) {
return (Component) => styled(Component)`
${styles}
`;
}
const Card = withStyledWrapper(`
padding: 24px;
background: white;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
`)(styled.div);
const Button = withStyledWrapper(`
padding: 12px 24px;
background: #667eea;
color: white;
border-radius: 8px;
`)(styled.button);
九、继承最佳实践 #
9.1 设计基础组件 #
jsx
import styled, { css } from 'styled-components';
const baseStyles = css`
font-family: inherit;
line-height: 1.5;
transition: all 0.2s;
`;
const BaseButton = styled.button`
${baseStyles}
padding: 12px 24px;
border-radius: 8px;
cursor: pointer;
border: none;
font-size: 16px;
`;
const BaseInput = styled.input`
${baseStyles}
padding: 12px 16px;
border: 2px solid #e0e0e0;
border-radius: 8px;
font-size: 16px;
&:focus {
border-color: #667eea;
outline: none;
}
`;
const BaseCard = styled.div`
${baseStyles}
padding: 24px;
background: white;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
`;
9.2 创建变体组件 #
jsx
const Button = {
Primary: styled(BaseButton)`
background: #667eea;
color: white;
&:hover {
background: #5a6fd6;
}
`,
Secondary: styled(BaseButton)`
background: transparent;
color: #667eea;
border: 2px solid #667eea;
&:hover {
background: #667eea;
color: white;
}
`,
Danger: styled(BaseButton)`
background: #ff4d4f;
color: white;
&:hover {
background: #ff7875;
}
`,
};
function App() {
return (
<>
<Button.Primary>Primary</Button.Primary>
<Button.Secondary>Secondary</Button.Secondary>
<Button.Danger>Danger</Button.Danger>
</>
);
}
9.3 继承层次控制 #
jsx
const Base = styled.button`
padding: 12px 24px;
border-radius: 8px;
`;
const Variant = styled(Base)`
background: #667eea;
color: white;
`;
const Size = styled(Variant)`
padding: 16px 32px;
font-size: 18px;
`;
const State = styled(Size)`
&:disabled {
opacity: 0.6;
cursor: not-allowed;
}
`;
十、总结 #
样式继承技巧速查表:
| 技巧 | 示例 |
|---|---|
| 继承元素 | styled(Button)\…`` |
| 继承组件 | styled(CustomComponent)\…`` |
| 覆盖样式 | 直接重写属性 |
| 扩展样式 | 添加新属性 |
| css 函数 | const mixin = css\…`` |
| 条件混合 | ${props => props.active && activeStyle} |
| transient props | $ 前缀避免 DOM 传递 |
下一步:学习 属性传递 掌握 attrs 方法的高级用法。
最后更新:2026-03-28