• React-View-UI组件库封装——Message 全局提示


    React-View-UI组件库封装——Message 全局提示

    前言

    React-View-UI已经更新了25个组件了,今天来写一下Message组件,这个组件目前还是很常用的,组件效果如下:
    在这里插入图片描述

    组件库文档如下:

    在这里插入图片描述
    在这里插入图片描述
    具体的交互可以在http://react-view-ui.com:92/#/common/message进行体验。

    API能力

    一共提供了如下的API:
    在这里插入图片描述
    组件主要调用方式如下:

    直接调用:

    Message.info('This is an info message!')
    
    • 1

    传入对象调用(扩展API都需要传入对象):

    Message.info({
          content: 'This is an info message!',
          duration: 3000,
          position: 'bottom'
          clearable: true,
          style: {
          	fontSize: '12px'
    	  }
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    组件类型接口

    import { CSSProperties } from 'react';
    
    interface MessageProps<T> {
      /**
       * @description 对象类型传参时的内容
       */
      content?: T;
      /**
       * @description Message类型
       */
      type?: 'info' | 'success' | 'warning' | 'error' | 'normal' | 'loading';
      /**
       * @description 显示时间
       * @default 3000ms
       */
      duration?: number;
      /**
       * @description 显示位置
       * @default top
       */
      position?: 'top' | 'bottom';
      /**
       * @description 出现可清除按钮
       * @default false
       */
      clearable?: boolean;
      /**
       * @description 自定义样式
       * @default {}
       */
      style?: CSSProperties;
    }
    
    export type { MessageProps };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    组件源码

    使用者所调用的Message.xxx函数其实就是在调用组件内部所定义的addInstance函数,往页面中不断加入div(Message组件),并在一定时延后自动关闭,这是组件的整体设计思路。

    import React, { useState, useEffect, useMemo, useRef, CSSProperties } from 'react';
    import ReactDOM from 'react-dom';
    import { MessageProps } from './interface';
    import './index.module.less';
    import {
      ExclamationCircleFilled,
      CheckCircleFilled,
      CloseCircleFilled,
      LoadingOutlined,
      CloseOutlined,
    } from '@ant-design/icons';
    
    let container: HTMLDivElement | null;
    let topMessageNum: number = 0;
    let bottomMessageNum: number = 0;
    
    function addInstance(
      type: 'info' | 'success' | 'warning' | 'error' | 'normal' | 'loading',
      props: string | MessageProps<string>,
    ) {
      let style: CSSProperties = {},
        duration: number = 3000,
        content,
        position: 'top' | 'bottom' = 'top',
        clearable = false;
      if (typeof props === 'object') {
        style = props.style || {};
        duration = props.duration || 3000;
        content = props.content;
        position = props.position ? props.position : 'top';
        clearable = props.clearable ? props.clearable : false;
      } else if (typeof props === 'string') {
        content = props;
      }
      const div = document.createElement('div');
      if (container) {
        container.appendChild(div);
      } else {
        container = document.createElement('div');
        container.setAttribute('class', 'all-container');
        document.body.appendChild(container);
        container.appendChild(div);
      }
      setTimeout(() => {
        if (position === 'top') {
          topMessageNum--;
        } else {
          bottomMessageNum--;
        }
        container?.removeChild(div);
      }, duration + 200);
      ReactDOM.render(
        <Message
          style={style}
          content={content}
          type={type}
          duration={duration}
          position={position}
          clearable={clearable}
        />,
        div,
      );
    }
    const Message = (props: MessageProps<string>) => {
      const { style, content, type, duration, position, clearable } = props;
      const [opac, setOpac] = useState(1);
      const messageDom = useRef<any>(null);
    
      useEffect(() => {
        if (position === 'top') {
          topMessageNum++;
        } else {
          bottomMessageNum++;
        }
        setTimeout(() => {
          (messageDom.current as HTMLElement).style.transition = '0.2s linear';
          (messageDom.current as HTMLElement).style.animation = 'none';
        }, 500);
        setTimeout(() => {
          setOpac(0);
        }, duration);
      }, []);
      useEffect(() => {
        const transform = position || 'top';
        (messageDom?.current as HTMLElement).style[transform] =
          (transform === 'top' ? topMessageNum : bottomMessageNum) * 70 + 'px';
      }, [topMessageNum, bottomMessageNum]);
    
      const messageIcon = useMemo(() => {
        if (type === 'info') {
          return <ExclamationCircleFilled style={{ color: '#1890ff', fontSize: '16px' }} />;
        } else if (type === 'error') {
          return <CloseCircleFilled style={{ color: '#f53f3f', fontSize: '16px' }} />;
        } else if (type === 'normal') {
          return <></>;
        } else if (type === 'success') {
          return <CheckCircleFilled style={{ color: '#19b42a', fontSize: '16px' }} />;
        } else if (type === 'warning') {
          return <ExclamationCircleFilled style={{ color: '#fa7d00', fontSize: '16px' }} />;
        } else if (type === 'loading') {
          return <LoadingOutlined style={{ color: '#1890ff', fontSize: '16px' }} />;
        }
      }, [type]);
    
      return (
        <div className="message-container" style={{ opacity: opac, ...style }} ref={messageDom}>
          {messageIcon}
          <span className="toast-content">{content}</span>
          {clearable && <CloseOutlined onClick={() => setOpac(0)} />}
        </div>
      );
    };
    
    Message.info = (props: string | MessageProps<string>) => {
      return addInstance('info', props);
    };
    Message.success = (props: string | MessageProps<string>) => {
      return addInstance('success', props);
    };
    Message.error = (props: string | MessageProps<string>) => {
      return addInstance('error', props);
    };
    Message.normal = (props: string | MessageProps<string>) => {
      return addInstance('normal', props);
    };
    Message.warning = (props: string | MessageProps<string>) => {
      return addInstance('warning', props);
    };
    Message.loading = (props: string | MessageProps<string>) => {
      return addInstance('loading', props);
    };
    
    export default Message;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134

    组件测试

    Message组件的单元测试代码如下:

    import React from 'react';
    import Message from '../../Message/index';
    import Enzyme from '../setup';
    import mountTest from '../mountTest';
    
    const { mount } = Enzyme;
    
    describe('Message', () => {
      beforeEach(() => {
        jest.useFakeTimers();
      });
    
      afterEach(() => {
        jest.runAllTimers();
      });
    
      it('test base Message show correctly', () => {
        Message.info('this is a test');
        expect(document.querySelectorAll('.all-container')).toHaveLength(1);
        expect(document.querySelectorAll('.message-container .toast-content')[0].innerHTML).toBe(
          'this is a test',
        );
      });
    
      it('test click five nums Message show num correctly', () => {
        for (let i = 0; i < 5; i++) {
          Message.info('content');
        }
        expect(document.querySelectorAll('.all-container')[0].childNodes.length).toBe(5);
      });
    
      it('test bottom transform Message show correctly', () => {
        Message.info({
          content: 'this is a test',
          duration: 3000,
          position: 'bottom',
        });
        expect(
          document.querySelectorAll('.message-container')[0].getAttribute('style')?.includes('bottom:'),
        );
      });
    
      it('test clearable Message correctly', () => {
        Message.info({
          content: 'this is a test',
          duration: 3000,
          clearable: true,
        });
        expect(document.querySelectorAll('.message-container')[0].childNodes.length).toBe(3);
      });
    });
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    组件库地址

    React-View-UI组件库线上链接:http://react-view-ui.com:92/#
    github:https://github.com/fengxinhhh/React-View-UI-fs
    npm:https://www.npmjs.com/package/react-view-ui

    开源不易,欢迎学习和体验,喜欢请多多支持,有问题请留言。

  • 相关阅读:
    神经网络权重初始化方法,神经网络如何训练权重
    EasyGBS如何解决对讲功能使用异常?
    unity hub (第一部)初学配置
    推荐几个制作svg的工具
    v73.结构
    计算机毕业设计之java+javaweb的新冠疫情下的校园出入系统
    React笔记——github案例(用到axios 和 pubsub)
    洛谷P6877 長いだけのネクタイ
    13.0、C语言——数据的存储(1)
    面了三十个人,说说我的真实感受
  • 原文地址:https://blog.csdn.net/m0_46995864/article/details/125550400