函数式组件 -- IconFont

函数式组件 -- IconFont

封装了一个iconFont的组件,方便之后的工作中进行使用;此组件提供了大量的接口,可以较为自由的根据业务场景进行配置。

1. 定义组件接口

接口可以大致分成几类:svg名称,样式,点击的回调,状态,状态颜色

typescript 复制代码
interface IconfontProps {
  icon: string; // svg::use的xlinkHref属性值
  style?: CSSProperties; // 覆盖样式
  onClick?: (...args: any) => void; // 点击回调
  noHover?: boolean;
  noActive?: boolean;
  disabled?: boolean;
  selected?: boolean; // 选中状态
  backgroundColor?: string;
  color?: string;
  hoveredColor?: string;
  hoveredBgColor?: string;
  activatedBgColor?: string;
}

2. 定义内部组件接口

内部接口可以大致分成几类:状态,状态颜色

typescript 复制代码
interface IconfontProps {
  noHover?: boolean; // 没有悬浮
  noActive?: boolean; // 没有激活
  disabled?: boolean; // 不可点击
  backgroundColor?: string; // 背景颜色
  color?: string; // 字体颜色
  hoveredBgColor?: string; // 悬浮背景变色
  activatedBgColor?: string; // 鼠标按下变色
  hoveredColor?: string; // 悬浮字体变色
}

3. 内部组件

使用styled-components这个js库中的styled, css实现一个css-in-js类型的内部组件Icon

typescript 复制代码
const Icon = styled.svg<IIntersectedProps>`
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  fill: currentColor;
  fill: ${(props: IIntersectedProps) => props.color};
  background-color: ${(props: IIntersectedProps) => props.backgroundColor};
  overflow: hidden;
  font-size: 16px;
  &:hover {
    background-color: ${(props: IIntersectedProps) =>
      props.noHover ? undefined : props.hoveredBgColor};
    fill: ${(props) => (props.noHover ? undefined : props.hoveredColor)};
  }
  &:active {
    background-color: ${(props: IIntersectedProps) =>
      props.noActive ? undefined : props.activatedBgColor};
    fill: ${(props: IIntersectedProps) => (props.noActive ? undefined : props.hoveredColor)};
  }
  ${(props: IIntersectedProps) =>
    props.disabled &&
    css`
      filter: grayscale(1) opacity(0.5);
    `};
`;

4. 外部组件

外部组件的基本结构就是:svg:use

typescript 复制代码
const IconFont = (props: IconfontProps) => {
  const {
    icon,
    style,
    backgroundColor = 'rgba(255,255,255,0.1)',
    color = 'grey',
    hoveredColor = 'blue',
    hoveredBgColor ='#fff',
    activatedBgColor = true,
    onClick = ()=>{},
    noHover = true,
    noActive = true,
    disabled = false,
  } = props;
  return (
    <Icon
      style={style}
      backgroundColor={backgroundColor}
      color={color}
      hoveredColor={hoveredColor}
      hoveredBgColor={hoveredBgColor}
      activatedBgColor={activatedBgColor}
      onClick={onClick}
      noHover={noHover}
      noActive={noActive}
      disabled={disabled}
    >
      <use xlinkHref={`#${icon}`} />
    </Icon>
  );
};

5. 全部代码

自定义组件文件的所有代码如下:

typescript 复制代码
// IconFont.tsx
import React, { CSSProperties } from "react";
import styled, { css } from "styled-components";
import "@assets/icons/iconfont";

interface IconfontProps {
  icon: string; // svg::use的xlinkHref属性值
  style?: CSSProperties; // 覆盖样式
  onClick?: (...args: any) => void; // 点击回调
  noHover?: boolean;
  noActive?: boolean;
  disabled?: boolean;
  selected?: boolean; // 选中状态
  backgroundColor?: string;
  color?: string;
  hoveredColor?: string;
  hoveredBgColor?: string;
  activatedBgColor?: string;
}

interface IIntersectedProps {
  noHover?: boolean; // 没有悬浮
  noActive?: boolean; // 没有激活
  disabled?: boolean; // 不可点击
  backgroundColor?: string; // 背景颜色
  color?: string; // 字体颜色
  hoveredBgColor?: string; // 悬浮背景变色
  activatedBgColor?: string; // 鼠标按下变色
  hoveredColor?: string; // 悬浮字体变色
}

const Icon = styled.svg<IIntersectedProps>`
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  fill: currentColor;
  fill: ${(props: IIntersectedProps) => props.color};
  background-color: ${(props: IIntersectedProps) => props.backgroundColor};
  overflow: hidden;
  font-size: 16px;
  &:hover {
    background-color: ${(props: IIntersectedProps) =>
      props.noHover ? undefined : props.hoveredBgColor};
    fill: ${(props) => (props.noHover ? undefined : props.hoveredColor)};
  }
  &:active {
    background-color: ${(props: IIntersectedProps) =>
      props.noActive ? undefined : props.activatedBgColor};
    fill: ${(props: IIntersectedProps) => (props.noActive ? undefined : props.hoveredColor)};
  }
  ${(props: IIntersectedProps) =>
    props.disabled &&
    css`
      filter: grayscale(1) opacity(0.5);
    `};
`;

export const IconFont = (props: IconfontProps) => {
  const {
    icon,
    style,
    backgroundColor = 'rgba(255,255,255,0.1)',
    color = 'grey',
    hoveredColor = 'blue',
    hoveredBgColor ='#fff',
    activatedBgColor = true,
    onClick = ()=>{},
    noHover = true,
    noActive = true,
    disabled = false,
  } = props;
  return (
    <Icon
      style={style}
      backgroundColor={backgroundColor}
      color={color}
      hoveredColor={hoveredColor}
      hoveredBgColor={hoveredBgColor}
      activatedBgColor={activatedBgColor}
      onClick={onClick}
      noHover={noHover}
      noActive={noActive}
      disabled={disabled}
    >
      <use xlinkHref={`#${icon}`} />
    </Icon>
  );
};
相关推荐
知识分享小能手1 天前
React学习教程,从入门到精通,React AJAX 语法知识点与案例详解(18)
前端·javascript·vue.js·学习·react.js·ajax·vue3
NeverSettle_1 天前
React工程实践面试题深度分析2025
javascript·react.js
学前端搞口饭吃1 天前
react reducx的使用
前端·react.js·前端框架
努力往上爬de蜗牛1 天前
react3面试题
javascript·react.js·面试
开心不就得了1 天前
React 进阶
前端·javascript·react.js
谢尔登1 天前
【React】React 哲学
前端·react.js·前端框架
学前端搞口饭吃1 天前
react context如何使用
前端·javascript·react.js
GDAL1 天前
为什么Cesium不使用vue或者react,而是 保留 Knockout
前端·vue.js·react.js
Dragon Wu2 天前
React state在setInterval里未获取最新值的问题
前端·javascript·react.js·前端框架
YU大宗师2 天前
React面试题
前端·javascript·react.js