欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

React实现全局组件的Toast轻提示效果

程序员文章站 2022-03-07 22:23:50
toast是常用的轻提示弹框,常用于页面loading和提示语弹窗。 本例基于react实现一个随时可调用且不随页面渲染的全局组件。 需求分析 toa...

toast是常用的轻提示弹框,常用于页面loading和提示语弹窗。

本例基于react实现一个随时可调用且不随页面渲染的全局组件。

需求分析

  • toast 不需要同页面一起被渲染,而是根据需要被随时调用。
  • toast 是一个轻量级的提示组件,它的提示不会打断用户操作,并且会在提示的一段时间后自动关闭。
  • toast 需要提供几种不同的消息类型以适应不同的使用场景。
  • toast 的方法必须足够简洁,以避免不必要的代码冗余。

如何使用

首先引入

import toast from './components/toast'

jsx中事件调用:

<button onclick={() => { toast.info('普通提示') }}>普通提示</button>

js中方法调用:

toast.info('普通提示')

回调方法:

const hideloading = toast.loading('加载中...', 0, () => {
  toast.success('加载完成')
})
settimeout(hideloading, 2000)

调用规则:

3个参数:

  • content 提示内容 string(loading方法为可选)
  • duration 提示持续时间 number,单位ms(可选)
  • onclose 提示关闭时的回调函数(可选)
toast.info("普通",2000)
toast.success("成功",1000,() => {
  console.log('回调方法')
}))
toast.error("错误")
toast.loading()

代码实现

目录结构:

React实现全局组件的Toast轻提示效果

  1. index.js:对外export接口,设置默认的参数值,全局创建或销毁toast的div。
  2. toast.js:toast具体显示的内容及多次调用toast时的状态管理。
  3. toast.css:toast的样式,费话不多说。

index.js:

import react from 'react'
import reactdom from 'react-dom'
import toast from './toast'
import './toast.css'

function createnotification() {
  const div = document.createelement('div')
  document.body.appendchild(div)
  const notification = reactdom.render(<toast />, div)
  return {
    addnotice(notice) {
      return notification.addnotice(notice)
    },
    destroy() {
      reactdom.unmountcomponentatnode(div)
      document.body.removechild(div)
    }
  }
}

let notification
const notice = (type, content, duration = 2000, onclose) => {
  if (!notification) notification = createnotification()
  return notification.addnotice({ type, content, duration, onclose })
}

export default {
  info(content, duration, onclose) {
    return notice('info', content, duration, onclose)
  },
  success(content = '操作成功', duration, onclose) {
    return notice('success', content, duration, onclose)
  },
  error(content, duration , onclose) {
    return notice('error', content, duration, onclose)
  },
  loading(content = '加载中...', duration = 0, onclose) {
    return notice('loading', content, duration, onclose)
  }
}

toast.js:

import react, { component } from 'react'

class toastbox extends component {
  constructor() {
    super()
    this.transitiontime = 300
    this.state = { notices: [] }
    this.removenotice = this.removenotice.bind(this)
  }

  getnoticekey() {
    const { notices } = this.state
    return `notice-${new date().gettime()}-${notices.length}`
  }

  addnotice(notice) {
    const { notices } = this.state
    notice.key = this.getnoticekey()

    // notices.push(notice);//展示所有的提示
    notices[0] = notice;//仅展示最后一个提示
    
    this.setstate({ notices })
    if (notice.duration > 0) {
      settimeout(() => {
        this.removenotice(notice.key)
      }, notice.duration)
    }
    return () => { this.removenotice(notice.key) }
  }

  removenotice(key) {
    const { notices } = this.state
    this.setstate({
      notices: notices.filter((notice) => {
        if (notice.key === key) {
          if (notice.onclose) settimeout(notice.onclose, this.transitiontime)
          return false
        }
        return true
      })
    })
  }

  render() {
    const { notices } = this.state
    const icons = {
      info: 'toast_info',
      success: 'toast_success',
      error: 'toast_error',
      loading: 'toast_loading'
    }
    return (
      <div classname="toast">
        {
          notices.map(notice => (
            <div classname="toast_bg" key={notice.key}>
              <div classname='toast_box'>
                <div classname={`toast_icon ${icons[notice.type]}`}></div>
                <div classname='toast_text'>{notice.content}</div> 
              </div>
            </div>
          ))
        }
      </div>
    )
  }
}

export default toastbox

toast.css:

.toast {
 position: fixed;
 left: 0;
 top: 0;
 z-index: 999;
 display: flex;
 flex-direction: column; }
 .toast_bg {
  position: fixed;
  width: 100%;
  height: 100%;
  left: 0;
  top: 0; }
 .toast_box {
  position: relative;
  left: 50%;
  top: 50%;
  width: 2.8rem;
  height: 2rem;
  margin: -1rem -1.4rem;
  background: rgba(0, 0, 0, 0.65);
  border-radius: .1rem;
  color: #fff; }
 .toast_text {
  position: absolute;
  bottom: 16%;
  text-align: center;
  width: 90%;
  margin: 0 5%;
  height: .28rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap; }
 .toast_icon {
  position: relative;
  left: 50%;
  top: 15%;
  margin: -.4rem;
  width: .8rem;
  height: .8rem; }
 .toast_loading {
  -webkit-animation: loading 1s steps(12, end) infinite;
  animation: loading 1s steps(12, end) infinite;
  background: url("data:image/png;base64,ivborw0kggoaaaansuheugaaacaaaaagcamaaabepirgaaaam1bmveuaaad///////////////////////////////////////////////////////////////+3lekcaaaaehrstlmaenca8kagsgdgqmcqudbwhylalqaaal1jrefuomu9u0kswyamk9jss/t/1zzt2pgezzq9rbemzyrgdi/70bo5jptjroaqvtonijvk5bw2ma9a7vvpk8odeqfbzectrdnyu+oo0b68wgk0mudpdxpociaizq5pkagiipaoew2rbvnyzom2yhbzdnkz/2ogam3ff5gmel8wisfh2kkzifigwfkk1b7nsbhnqfy4m2+pghbodnsg7y8thm2njiy8gbgcaeua9ggnjbxh6fjv+nxifvympaftcqznk1qziaaaaabjru5erkjggg==") no-repeat;
  background-size: 100%; }
 .toast_success {
  background: url("data:image/png;base64,ivborw0kggoaaaansuheugaaacaaaaagcamaaabepirgaaaam1bmveuaaad///////////////////////////////////////////////////////////////+3lekcaaaaehrstlma8daq0gbp4lcggmbwijbaittdjaaaainjrefuomvdkusowyambbh5hucauf9pk1slohf438x2lpn52f09+8vufinb/gighj8fouejycuoqdxibsd7pdcmik7xc9wcfmldo3t20scgx287ne13pwdu89noj3g3macmjdanqigrtlj8oi1ed1gmdmcb7wxiyx8qdqzjim5em3smbyvicdcorcqsaaaaaelftksuqmcc") no-repeat;
  background-size: 100%; }
 .toast_error {
  background: url("data:image/png;base64,ivborw0kggoaaaansuheugaaacaaaaagbamaaacbvgfhaaaamfbmveuaaad///////////////////////////////////////////////////////////87tqqwaaaad3rstlma0bdamodwukbgsccaqjclzvpvaaaa0uleqvqoz2mgeraclv9o44dgc8b/b4kvbta+t/3xdgewivjpg6acbl8ngnxlp0an+l8iwtd6dzfm2w+y3v5smgw/acba9rms9zsctiaph2qr608ghoukqj4xa8p8akcap5cwf2jgupwilpwcfdj/amrryjihcnl8azkj1afkacuygnhbpso7micugbqw8h4eev/b5ssdfya4makywjanfd+aai3cyz9bdom63rdkdegq0ze9h+l9zadcdeigt2/wqezewwvepghgyedefgzuegyaw05xi3jssvwaaaaasuvork5cyii=") no-repeat;
  background-size: 100%; }
 .toast_info {
  background: url("data:image/png;base64,ivborw0kggoaaaansuheugaaacaaaaagbamaaacbvgfhaaaalvbmveuaaad///////////////////////////////////////////////////////+hskubaaaadnrstlma4ccawkbamjbg8naqunhwlbcaaac+surbvcjpyyasslfse+1cgobzyr0dgocxyhwmv4dtckwzck8uoajzdyda1c2h8nnexuayr99bjnf6ctmbtwhm+quacuuhimh6bkz14qegafcyspdigsxifmkae2cyjwak6gqqaozpgurfa0kaa0t6jsae2ecm7lnacdc9bhlvggacia6gafylohbec9xqqleeqkwfa4i1eifbaenzunmvhsbox/acpvcxawgzcdedgtmaghhheywishn4vbigapvrt5yzufhuaaaaaelftksuqmcc") no-repeat;
  background-size: 100%; }

@-webkit-keyframes loading {
 0% {
  -webkit-transform: rotate3d(0, 0, 1, 0deg);
  transform: rotate3d(0, 0, 1, 0deg); }
 100% {
  -webkit-transform: rotate3d(0, 0, 1, 360deg);
  transform: rotate3d(0, 0, 1, 360deg); } }

@keyframes loading {
 0% {
  -webkit-transform: rotate3d(0, 0, 1, 0deg);
  transform: rotate3d(0, 0, 1, 0deg); }
 100% {
  -webkit-transform: rotate3d(0, 0, 1, 360deg);
  transform: rotate3d(0, 0, 1, 360deg); } }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。