手写antd提示组件

1. 功能需求

支持成功和提示类型的消息展示,可以连续弹出,并隔2秒消失。

2. 代码实现

jsx
import './JKMessage.css'

import { InfoCircleFilled, CheckCircleFilled } from '@ant-design/icons'

import { createRoot } from 'react-dom/client'

import PropTypes from 'prop-types'



function JKMessage({ msg = '', icon = null }) {

  return (

    <div className="jk-ant-message-notice">

      <div className="jk-ant-message-notice-content">{icon} {msg}</div>

    </div>

  )

}



const jkMessage = {

  wrapper: null,

  root: null,

  list: [],

  showAndHide(msg, icon) {

    // 有root需要提前卸载

    if (this.root) {

      this.root.unmount()

      this.root = null

    }

    // 创建消息挂载DOM位置

    if (!this.wrapper) {

      this.wrapper = document.createElement('div')

      this.wrapper.className = 'jk-ant-message'

      document.body.appendChild(this.wrapper)

    }

    if (!this.root) {

      // root不能多次创建,否则会报错

      this.root = createRoot(this.wrapper)

      this.list.push(

        <JKMessage key={this.list.length} msg={msg} icon={icon} />

      )

      this.root.render(this.list)

    }



    setTimeout(() => {

      // 一个一个消息挨个清除

      this.list.shift()

      this.root = null

      this.wrapper.children[0].remove()

      // 如果wrapper里面已经清除完毕所有消息,就清楚wrapper

      if (this.list.length === 0) {

        this.wrapper.remove()

        this.wrapper = null

      }

    }, 2000)

  },

  info(msg) {

    this.showAndHide(msg, <InfoCircleFilled style={{ color: 'blue' }} />)

  },

  success(msg) {

    this.showAndHide(msg, <CheckCircleFilled style={{ color: 'green' }} />)

  }

}

JKMessage.propTypes = {

  msg: PropTypes.string,

  icon: PropTypes.element

}

export default jkMessage
css
.jk-ant-message {

    box-sizing: border-box;

    margin: 0;

    padding: 0;

    color: rgba(0, 0, 0, 0.88);

    font-size: 14px;

    line-height: 1.5714285714285714;

    list-style: none;

    font-family: -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,'Noto Sans',sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol','Noto Color Emoji';

    position: fixed;

    top: 8px;

    width: 100%;

    pointer-events: none;

    z-index: 1010;

    left: 50%;

    transform: translateX(-50%);

    top: 8px;

}

.jk-ant-message-notice {

    padding: 8px;

    text-align: center;

}

.jk-ant-message-notice-content {

    display: inline-block;

    padding: 9px 12px;

    background: #ffffff;

    border-radius: 8px;

    box-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05);

    pointer-events: all;

}
js
import JKButton from './JKButton/JKButton.jsx'

import JKRate from './JKRate/JKRate.jsx'

import jkMessage from './JKMessage/JKMessage.jsx'



export  {JKButton, JKRate, jkMessage}
jsx
import { Button, message, Space } from 'antd'

import {jkMessage} from './JKAntd'



function App() {

  const handleClick1 = () => {

    message.info('hello Antd! ')

  }

  const handleClick2 = () => {

    message.success("操作成功!")

  }

  const handleClick3 = () => {

    jkMessage.info('hello Antd! ')

  }

  const handleClick4 = () => {

    jkMessage.success("操作成功!")

  }

  return (

    <>

      hello App

      <br />

      <br />

      <Space>

        <Button type="primary" onClick={handleClick1}>点击1</Button>

        <Button type="primary" onClick={handleClick2}>点击2</Button>

      </Space>

      <br />

      <br />

      <Space>

        <Button type="primary" onClick={handleClick3}>点击1</Button>

        <Button type="primary" onClick={handleClick4}>点击2</Button>

      </Space>

    </>

  )

}

export default App
运行效果: ![Alt text](/web/react/images/45645646105248.gif)

评论