手动实现一个react的message组件

手动实现一个react的message组件

组件目录如下:
在这里插入图片描述

  1. Message入口文件
// index.tsx
import { useState,useEffect } from 'react';
import * as ReactDOM from 'react-dom';
import Msg from './Msg';
import { MessageApi,List } from './config';
import './index.less';

let add: (L: List) => void;
export const MessageContainer = () => {
  const [lists ,setList] = useState<List[]>([]);
  const remove = (L:List) => {
    const { key } = L;
    setList((pre:List[]) => ( pre.filter((each:List) => key !== each.key) ))
  }

  add = (option:List) => {
    setList((pre:List[])=>{
      const obj = [...pre,option ];
      setTimeout(() => {
          remove(option)
        }, 3000)
        return obj
    })
    // 最好不用下面这个写法,当同时调用两个message时候,只会显示最后调用那次
    // const obj = [...lists,option ];
    // setList(obj);
    // setTimeout(() => {
    //   remove(option)
    // }, timeout)
  }

  useEffect(() => {
    if (lists.length > 10) {
      lists.shift();
    }
  }, [lists])

  return (
    <>
      {
        lists.map(({ text, key, type }) => (
            <Msg key={key} type={type} text={text} />
        ))
      }
    </>
  )
} 

// 获取唯一id
const getId = () => {
  return (Math.random() * 1000).toFixed()
}

// 暴露的message-API
const $message: MessageApi = {
  info: (text) => {
    add({
      text,
      key: getId(),
      type: 'info'
    })
  },
  success: (text) => {
    add({
      text,
      key: getId(),
      type: 'success'
    })
  },
  warning: (text) => {
    add({
      text,
      key: getId(),
      type: 'warning'
    })
  },
  error: (text) => {
    add({
      text,
      key: getId(),
      type: 'error'
    })
  }
}
export default $message;

// 挂载容器到页面
const createMessage = () => {
  let el = document.getElementById('#message-wrap');
  // 这一步是必要的的,因为在执行到这里的时候,页面还没有挂载,所以获取不到el节点
  if (!el) {
      el = document.createElement('div')
      el.className = 'message-wrap'
      el.id = 'message-wrap'
      document.body.append(el)
  }
  ReactDOM.render( <MessageContainer />, el);
}
createMessage();

  1. Message样式文件
//index.less
.message-wrap{
    position: fixed;
    left: 50%;
    top: 60px;
    transform: translate(-50%);
    z-index: 1000;
    .message{
      height: 34px;
      min-width: 180px;
      padding: 0px 10px;
      font-size: 12px;
      margin-top: 20px;
      display: flex;
      align-items: center;
      border-radius: 4px;
      box-shadow: 0 0 8px #ddd;
      border: 1px solid #eee;
      .icon {
        width: 10px;
        height: 10px;
        border-radius: 50%;
        margin-right: 6px;
      }
    }
    .info {
        color: #5a98e9;
        >.icon{
          background: #5a98e9;
        }
      }
    .error {
      color: #ff4d4f;
      >.icon{
        background: #ff4d4f;
      }
    }
     .warning {
      color: #faad14;
      >.icon{
        background: #faad14;
      }
    }
     .success {
      color: #52c41a;
      >.icon{
        background: #52c41a;
      }
    }
}
  1. Message消息模板
// Msg.tsx
const Msg = ({type, text }:{ type:string,text: string }) => {
  return (
        <div className={`message ${type}`}>
            <span className='icon' />
            <span>{text}</span>
        </div>
  );
};

export default Msg;

  1. ts校验的配置文件
// config.ts
export interface MessageApi {
    info: (text: string) => void;
    success: (text: string) => void;
    warning: (text: string) => void;
    error: (text: string) => void;
}
  
export interface List {
    text: string;
    key: string;
    type: 'info' | 'success' | 'error' | 'warning';
}
  
  1. 使用react版本的message
import $message from '../component/index';
$message.success('我是一条成功的自定义消息')

效果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值