react + tsx手把手自定义messages组件

模拟elementUI的message提示组件,自定义属于自己的messages组件

确定组件需求

  1. 组件应当有几种类型
  2. 用户需要控制组件的什么

首先是组件的类型

拿elementUI的message类型来说,我们枚举出四种类型,如下代码

image.png

用户需要控制的

我们把用户的需求统一封装成一个接口

image.png

接下来就是代码实现。

代码实现

我们抛出并定义一个 Message, 他里面有私有成员colorObj、options

image.png

options: 顾名思义,是整个message组件的配置对象

colorObj: 是每个类型显示不同样式

定义一个成员函数,用于创建dom,并且插入到项目根节点

image.png

image.png

在类里面初始化该函数,并且赋值传过来的配置对象

image.png

移除该元素

image.png

用法

image.png

效果

image.png

完整源码

import './messages.scss'

export enum enumMessageType {
  SUCCESS = 'success',
  WARNING = 'warning',
  INFO = 'info',
  ERROR = 'error'
}

export interface InterMessagesProps {
  title: string, // 提示内容
  type: enumMessageType, // 类型(只允许传枚举中的一种)
  duration?: number, // 间隔时间
  showClose?: boolean, // 是否显示关闭icon
  center?: boolean, // 是否剧中
  offset?: number // 偏移量
}

export default class Messages {
  private options: InterMessagesProps;

  private colorObj = {
    [enumMessageType.SUCCESS]: {
      color: '#67C284',
      bg: '#F0F9EB',
      icon: 'icon-xiaoxi-chenggong'
    },

    [enumMessageType.WARNING]: {
      bg: '#FDF6EC',
      color: '#E6A242',
      icon: 'icon-jinggao'
    },

    [enumMessageType.INFO]: {
      bg: '#EDF2FC',
      color: '#909399',
      icon: 'icon-jinggao'
    },

    [enumMessageType.ERROR]: {
      bg: '#FEF0F0',
      color: '#F66E6C',
      icon: 'icon-shibai'
    }
  }

  constructor(options: InterMessagesProps) {
    this.options = {
      duration: 3000,
      showClose: false,
      center: false,
      offset: 20,
      ...options
    }

    this.initMessages()
  }

  initMessages() {
    this.getEleDom('#root')?.appendChild(this.messageDom())
  }

  messageDom() {
    const { offset, type, duration } = this.options
    const { bg, color, icon } = this.colorObj[type]
    const MessageDom = document.createElement('div')
    MessageDom.className = 'large_message'
    MessageDom.style.top = `${offset}px`
    MessageDom.style.background = `${bg}`
    MessageDom.style.color = `${color}`
    MessageDom.style.border = `1px solid ${color}`

    const timersNow = setTimeout(() => {
      MessageDom.style.opacity = `1`
      MessageDom.style.right = `5%`
      clearTimeout(timersNow)
    }, 0)

    const timer = setTimeout(() => {
      MessageDom.style.opacity = `0`
      MessageDom.style.right = `-100%`
      clearTimeout(timer)
    }, duration)

    const clearDom = setTimeout(() => {
      this.close()
      clearTimeout(clearDom)
    }, duration as number + 400)

    MessageDom.appendChild(this.childDom())
    MessageDom.insertBefore(this.iconDom(icon), MessageDom.firstChild)
    return MessageDom
  }

  iconDom(icon: string) {
    const iconDom = document.createElement('i')
    iconDom.className = `iconfont ${icon}`

    return iconDom
  }

  close() {
    this.getEleDom('.large_message')?.remove()
  }

  childDom() {
    const { title, center } = this.options
    const childDom = document.createElement('p')
    childDom.className = 'large_message_child'
    childDom.innerHTML = title
    childDom.style.textAlign = center ? 'center' : 'left'
    return childDom
  }

  getEleDom(dom: string) {
    return document.querySelector(dom)
  }
}

// messages.scss 部分
@import './iconfont.scss'; // icon图标自己替换哦;

.large_message {
  width: 380px;
  padding: 10px;

  display: flex;
  align-items: center;

  position: fixed;
  right: -100%;

  opacity: 0;
  transition: right .4s, opacity .3s;

  z-index: 99999;

  border-radius: 5px;

  &_child {
    padding-left: 10px;
    margin-bottom: 0;

    font-size: 14px;
  }

  .iconfont {
    padding-left: 5px;
  }
}

复制代码

如果觉得这篇文章对你有帮助的化,请点个小赞赞哦!

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享