当前位置: 移动技术网 > IT编程>开发语言>JavaScript > React实现全局组件的Toast轻提示效果

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

2019年06月03日  | 移动技术网IT编程  | 我要评论

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()

代码实现

目录结构:

  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); } }

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网