You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何更简洁地编写重复样式的Styled Components图标组件

问题:Styled Components批量处理图标样式的简洁写法?

我在项目中使用Styled Components进行样式开发,项目里定义了大量SVG图标,当前样式文件my-component.styles.ts的代码如下:

import { ReactComponent as CloseIcon } from 'svg/close.svg';
import { ReactComponent as OpenIcon } from 'svg/open.svg';
import { ReactComponent as DeleteIcon } from 'svg/delete.svg';
import { ReactComponent as CheckIcon } from 'svg/check.svg';
// 更多图标导入...

export const StyledCloseIcon = styled(CloseIcon)`
  width: 20px;
  fill: white;
`;

export const StyledOpenIcon = styled(OpenIcon)`
  width: 20px;
  fill: white;
`;

export const StyledDeleteIcon = styled(DeleteIcon)`
  width: 20px;
  fill: white;
`;

export const StyledCheckIcon = styled(CheckIcon)`
  width: 20px;
  fill: white;
`;
// 更多Styled图标定义...

所有图标都使用完全相同的样式,但在其他组件中使用时,需要逐个导入:

import {
  StyledCloseIcon,
  StyledOpenIcon,
  StyledDeleteIcon,
  StyledCheckIcon
} from './my-component.styles';

之后通过<StyledCloseIcon />这样的方式使用。请问有没有更简洁的写法?


解决方案

方法1:批量生成Styled图标组件

通过对象映射+动态生成的方式,避免重复编写相同的样式代码:

// my-component.styles.ts
import styled from 'styled-components';
import { ReactComponent as CloseIcon } from 'svg/close.svg';
import { ReactComponent as OpenIcon } from 'svg/open.svg';
import { ReactComponent as DeleteIcon } from 'svg/delete.svg';
import { ReactComponent as CheckIcon } from 'svg/check.svg';

// 把所有图标存入映射对象
const rawIcons = {
  Close: CloseIcon,
  Open: OpenIcon,
  Delete: DeleteIcon,
  Check: CheckIcon
  // 新增图标直接在这里添加即可
};

// 定义通用图标样式
const baseIconStyle = `
  width: 20px;
  fill: white;
`;

// 批量生成并导出Styled组件
export const StyledIcons = Object.fromEntries(
  Object.entries(rawIcons).map(([iconName, IconComponent]) => [
    iconName,
    styled(IconComponent)`${baseIconStyle}`
  ])
);

使用方式:

import { StyledIcons } from './my-component.styles';

// 在组件中使用
<StyledIcons.Close />
<StyledIcons.Open />

方法2:封装通用图标组件(更具扩展性)

如果后续需要支持自定义尺寸、颜色等样式,推荐封装一个通用图标组件,兼顾简洁性和灵活性:

// components/Icon.tsx
import styled from 'styled-components';
import { ReactComponent as CloseIcon } from 'svg/close.svg';
import { ReactComponent as OpenIcon } from 'svg/open.svg';
import { ReactComponent as DeleteIcon } from 'svg/delete.svg';
import { ReactComponent as CheckIcon } from 'svg/check.svg';

// 图标名称与组件的映射
const iconComponents = {
  close: CloseIcon,
  open: OpenIcon,
  delete: DeleteIcon,
  check: CheckIcon
};

// 基础样式组件,支持自定义属性
const StyledIcon = styled.svg`
  width: ${props => props.$size || '20px'};
  fill: ${props => props.$color || 'white'};
`;

// 定义组件Props类型
interface IconProps {
  name: keyof typeof iconComponents;
  $size?: string;
  $color?: string;
}

// 导出通用图标组件
export const Icon = ({ name, $size, $color }: IconProps) => {
  const Component = iconComponents[name];
  return <StyledIcon as={Component} $size={$size} $color={$color} />;
};

使用方式:

import { Icon } from './components/Icon';

// 默认样式使用
<Icon name="close" />
// 自定义尺寸和颜色
<Icon name="delete" $size="24px" $color="#ff4444" />

方法3:复用通用Styled组件

如果不想改动太多现有代码,可以先定义一个基础样式组件,再用它包装各个图标:

// my-component.styles.ts
import styled from 'styled-components';
import { ReactComponent as CloseIcon } from 'svg/close.svg';
import { ReactComponent as OpenIcon } from 'svg/open.svg';
import { ReactComponent as DeleteIcon } from 'svg/delete.svg';
import { ReactComponent as CheckIcon } from 'svg/check.svg';

// 通用图标样式组件
export const BaseStyledIcon = styled.svg`
  width: 20px;
  fill: white;
`;

// 用基础组件包装各个图标,统一导出
export const StyledCloseIcon = () => <BaseStyledIcon as={CloseIcon} />;
export const StyledOpenIcon = () => <BaseStyledIcon as={OpenIcon} />;
export const StyledDeleteIcon = () => <BaseStyledIcon as={DeleteIcon} />;
export const StyledCheckIcon = () => <BaseStyledIcon as={CheckIcon} />;

// 可选:导出统一对象方便批量导入
export const Icons = {
  Close: StyledCloseIcon,
  Open: StyledOpenIcon,
  Delete: StyledDeleteIcon,
  Check: StyledCheckIcon
};

使用方式:

import { Icons } from './my-component.styles';

<Icons.Close />

内容的提问来源于stack exchange,提问作者Leo Messi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 20:50:29