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

553 阅读2分钟

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

TIP 👉 英雄者,胸怀大志,腹有良策,有包藏宇宙之机,吞吐天地之志者也。——《三国演义》

前言

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

Tag 图标

import

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

Props

1. prefixCls
  • 类型:string
  • 默认值:'is-tag'
  • 说明:设置标签外部元素样式
2. color
  • 类型:string
  • 默认值:无
  • 说明:标签样式 取值 根据颜色设置:white、pink、red、yellow、orange、cyan、green、blue、purple 根据状态设置:default、error、warn、success、info
3. checked
  • 类型:bool
  • 默认值:无
  • 说明:当前标签进行切换设置该属性,可进行样式切换
4. onClose
  • 类型:func
  • 默认值:无
  • 说明:关闭标签的回调
5. icon
  • 类型:string
  • 默认值:无
  • 说明:设置标签图标
6. transparent
  • 类型:bool
  • 默认值:false
  • 说明:设置标签背景是否透明
7. className
  • 类型:string | array | object(key: 样式名,value: bool)
  • 默认值:无
  • 说明:最外层元素样式

让我们实现一款这样的组件

import React from 'react';
import { Component, PropTypes } from '../utils/';
import Icon from '../icon';
import './tag.scss';

export default class Tag extends Component {
    constructor(props) {
        super(props);
        this.state = {
            visible: true,
        };
    }

    // 关闭按钮操作
    close = (e) => {
        const { onClose, children } = this.props;
        onClose && onClose(e, children);
        console.log('ddd', e.isDefaultPrevented())
        if (e.isDefaultPrevented()) return;
        this.setState({
            visible: false,
        });
    }

    isColorValue(color) {
        const span = document.createElement('span');
        span.style.color = color;
        if (span.style.color !== '') return true;
        return false;
    }
    // 校验传入的色值
    isPresetColor(color) {
        return /^(white|pink|red|yellow|orange|cyan|green|blue|purple)$/.test(color);
    }

    render() {
        const { prefixCls, color, onClose, icon, className, checked, children, transparent, ...others } = this.props;
        const { visible } = this.state;
        let colors = '';

        // 获取标签样式
        switch (color) {
            case 'default': colors = 'white'; break;
            case 'error': colors = 'red'; break;
            case 'warn': colors = 'orange'; break;
            case 'success': colors = 'green'; break;
            case 'info': colors = 'blue'; break;
            default: colors = color; break;
        }

        const cls = this.classNames(prefixCls, className, checked, {
            [`${prefixCls}-${colors}`]: this.isPresetColor(colors) && color,
            [`${prefixCls}-checkable`]: checked === false || checked === true,
            transparent: transparent
        });

        // 自定义颜色值
        const styles = {};
        if (!this.isPresetColor(colors) && this.isColorValue(colors)) {
            styles.backgroundColor = colors;
        }

        return visible ? (
            <span {...others} style={styles} className={cls}>
                {/* 带按钮标签 */}
                {icon && <Icon type={icon} />}
                {children}
                {/* 定义删除按钮 */}
                {(onClose) &&
                <Icon type="close"
                      className={this.classNames({
                          [`${prefixCls}-icon-close`]: onClose,
                      })}
                      onClick={this.close}
                />
                }
      </span>
        ) : null;
    }
}

Tag.propTypes = {
    // 自定义标签样式
    prefixCls: PropTypes.string,
    // 标签显示的颜色
    color: PropTypes.string,
    // 标签是否存在背景色 false不被选中 无背景
    checked: PropTypes.bool,
    // 删除标签回掉函数
    onClose: PropTypes.func,
    // 标签前的图标
    icon: PropTypes.string,
    // 标签是否存在背景
    transparent: PropTypes.bool,
    // 最外层元素样式
    className: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.array,
        PropTypes.objectOf(PropTypes.bool)
    ])
};

Tag.defaultProps = {
    // 标签默认显示状态
    color: 'default',
    // 标签样式默认值
    prefixCls: 'is-tag',
    // 标签是否有背景
    transparent: false,
};

样式这块就先不放了

「欢迎在评论区讨论」

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