如何用react封装一款SVG 图标组件

3,814 阅读2分钟

这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战

TIP 👉 不经一番寒彻骨,怎得梅花扑鼻香。____黄蘖禅师《上堂开示颂》

前言

Web Component是前端界一直非常热衷的一个领域,用第三方组件化的框架去实现的话,你需要依赖框架本身很多东西,很多时候我们只是简单的几个组件,不是很大,也不是很多,所以为了保证组件的`轻量,简单`,其实这个时候我们并不想采用第三方的框架。

SVG 图标

import

import SvgIcon from '@/components/SvgIcon/SvgIcon.js';

Props

1. iconName
  • 类型:string (必填)
  • 默认值:无
  • 说明:图标名称,必须与 src/components/SvgIcon/icon 目录下的svg文件的名称一致
2. className
  • 类型:string | array | object(key: 样式名,value: bool)
  • 默认值:无
  • 说明:最外层元素样式
<SvgIcon iconName="user" className = {'my-class'}></SvgIcon>
<SvgIcon iconName="user" className = {['my-class1', 'my-class2']}></SvgIcon>
<SvgIcon iconName="user" className = {{'my-class1': true}}></SvgIcon>

设置图标大小和颜色

  • 图标的大小取决于当前字体的大小,图标的颜色取决于当前字体的颜色,可通过以下两种方式来设置图标的大小和颜色:
1. 通过父元素的样式来设置
<div class="icon-wrapper">
    <SvgIcon iconName="user"></SvgIcon>
</div>
.icon-wrapper {
    font-size: 50px;
    color: red;
}
2. 自定义class来设置
<SvgIcon iconName="user" className="icon-red"></SvgIcon>
.icon-red {
    font-size: 50px;
    color: red;
}

增加新的图标

  • 只需要将新的 svg 放到 src/components/SvgIcon/icon 目录下即可
/**
 * SVG 图标
 */
import React from 'react';
import PropTypes from 'prop-types';
// 为保证测试用例运行,不使用webpack内置utils模块,单独引入
import utils from '../../js/common/utils/index.js';
import './SvgIcon.scss';

// 动态加载svg图标文件
const requireAll = requireContext => requireContext.keys().map(requireContext)
const req = require.context('./icon', false, /.svg$/)
requireAll(req)

/**
 * SVG 图标组件
 */
export default class SvgIcon extends React.Component {
    // 入参类型检查
    static propTypes = {
        // 图标名称(必须与icon目录下文件名一致)
        iconName: PropTypes.string.isRequired,
        // 最外层元素样式
        className: PropTypes.oneOfType([
            PropTypes.string,
            PropTypes.array,
            PropTypes.objectOf(PropTypes.bool)
        ])
    }

    constructor(props) {
        super(props);
    }

    /**
     * 选择框最外层需要的class
     * @returns {string}
     */
    getSvgClassName(){
        return utils.clasx(this.props.className, {
            'svg-icon': true
        });
    }

    render() {
        return (
            <svg className={this.getSvgClassName()} aria-hidden="true">
                <use xlinkHref={'#icon-' + this.props.iconName}></use>
            </svg>
        );
    }
}

样式这块就先不放了

「欢迎在评论区讨论」

希望看完的朋友可以给个赞,鼓励一下