经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JSJS库框架 » JavaScript » 查看文章
React实现全局组件的Toast轻提示效果
来源:jb51  时间:2018/9/25 19:02:27  对本文有异议

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

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

需求分析

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

如何使用

首先引入

  1. import Toast from './components/toast'

JSX中事件调用:

  1. <button onClick={() => { Toast.info('普通提示') }}>普通提示</button>

JS中方法调用:

  1. Toast.info('普通提示')

回调方法:

  1. const hideLoading = Toast.loading('加载中...', 0, () => {
  2. Toast.success('加载完成')
  3. })
  4. setTimeout(hideLoading, 2000)

调用规则:

3个参数:

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

代码实现

目录结构:

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

index.js:

  1. import React from 'react'
  2. import ReactDOM from 'react-dom'
  3. import Toast from './toast'
  4. import './toast.css'
  5.  
  6. function createNotification() {
  7. const div = document.createElement('div')
  8. document.body.appendChild(div)
  9. const notification = ReactDOM.render(<Toast />, div)
  10. return {
  11. addNotice(notice) {
  12. return notification.addNotice(notice)
  13. },
  14. destroy() {
  15. ReactDOM.unmountComponentAtNode(div)
  16. document.body.removeChild(div)
  17. }
  18. }
  19. }
  20.  
  21. let notification
  22. const notice = (type, content, duration = 2000, onClose) => {
  23. if (!notification) notification = createNotification()
  24. return notification.addNotice({ type, content, duration, onClose })
  25. }
  26.  
  27. export default {
  28. info(content, duration, onClose) {
  29. return notice('info', content, duration, onClose)
  30. },
  31. success(content = '操作成功', duration, onClose) {
  32. return notice('success', content, duration, onClose)
  33. },
  34. error(content, duration , onClose) {
  35. return notice('error', content, duration, onClose)
  36. },
  37. loading(content = '加载中...', duration = 0, onClose) {
  38. return notice('loading', content, duration, onClose)
  39. }
  40. }

toast.js:

  1. import React, { Component } from 'react'
  2.  
  3. class ToastBox extends Component {
  4. constructor() {
  5. super()
  6. this.transitionTime = 300
  7. this.state = { notices: [] }
  8. this.removeNotice = this.removeNotice.bind(this)
  9. }
  10.  
  11. getNoticeKey() {
  12. const { notices } = this.state
  13. return `notice-${new Date().getTime()}-${notices.length}`
  14. }
  15.  
  16. addNotice(notice) {
  17. const { notices } = this.state
  18. notice.key = this.getNoticeKey()
  19.  
  20. // notices.push(notice);//展示所有的提示
  21. notices[0] = notice;//仅展示最后一个提示
  22. this.setState({ notices })
  23. if (notice.duration > 0) {
  24. setTimeout(() => {
  25. this.removeNotice(notice.key)
  26. }, notice.duration)
  27. }
  28. return () => { this.removeNotice(notice.key) }
  29. }
  30.  
  31. removeNotice(key) {
  32. const { notices } = this.state
  33. this.setState({
  34. notices: notices.filter((notice) => {
  35. if (notice.key === key) {
  36. if (notice.onClose) setTimeout(notice.onClose, this.transitionTime)
  37. return false
  38. }
  39. return true
  40. })
  41. })
  42. }
  43.  
  44. render() {
  45. const { notices } = this.state
  46. const icons = {
  47. info: 'toast_info',
  48. success: 'toast_success',
  49. error: 'toast_error',
  50. loading: 'toast_loading'
  51. }
  52. return (
  53. <div className="toast">
  54. {
  55. notices.map(notice => (
  56. <div className="toast_bg" key={notice.key}>
  57. <div className='toast_box'>
  58. <div className={`toast_icon ${icons[notice.type]}`}></div>
  59. <div className='toast_text'>{notice.content}</div>
  60. </div>
  61. </div>
  62. ))
  63. }
  64. </div>
  65. )
  66. }
  67. }
  68.  
  69. export default ToastBox

toast.css:

  1. .toast {
  2. position: fixed;
  3. left: 0;
  4. top: 0;
  5. z-index: 999;
  6. display: flex;
  7. flex-direction: column; }
  8. .toast_bg {
  9. position: fixed;
  10. width: 100%;
  11. height: 100%;
  12. left: 0;
  13. top: 0; }
  14. .toast_box {
  15. position: relative;
  16. left: 50%;
  17. top: 50%;
  18. width: 2.8rem;
  19. height: 2rem;
  20. margin: -1rem -1.4rem;
  21. background: rgba(0, 0, 0, 0.65);
  22. border-radius: .1rem;
  23. color: #fff; }
  24. .toast_text {
  25. position: absolute;
  26. bottom: 16%;
  27. text-align: center;
  28. width: 90%;
  29. margin: 0 5%;
  30. height: .28rem;
  31. overflow: hidden;
  32. text-overflow: ellipsis;
  33. white-space: nowrap; }
  34. .toast_icon {
  35. position: relative;
  36. left: 50%;
  37. top: 15%;
  38. margin: -.4rem;
  39. width: .8rem;
  40. height: .8rem; }
  41. .toast_loading {
  42. -webkit-animation: loading 1s steps(12, end) infinite;
  43. animation: loading 1s steps(12, end) infinite;
  44. background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAM1BMVEUAAAD///////////////////////////////////////////////////////////////+3leKCAAAAEHRSTlMAENCA8KAgsGDgQMCQUDBwhylaLQAAAL1JREFUOMu9U0kSwyAMK9jsS/T/1zZt2pgEZzq9RBeMZYRGDI/70bO5JptjrOAQVTonIJVK5bW2ma9A7VvpK8OdeQfbZectrDnyU+Oo0b68wGK0muDPdxpOciaizq5pkAgiIPAoew2rBVNYZoM2YHbZDNKz/2Ogam3ff5gMEL8wisfh2KKZiFiGWFkk1B7NSbhNQFy4M2+PghbODNsg7y8THM2njiy8gBgcaEUA9GgNJbxh6fJv+NxiFvYmPAFtCQZNK1qZIAAAAABJRU5ErkJggg==") no-repeat;
  45. background-size: 100%; }
  46. .toast_success {
  47. background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAM1BMVEUAAAD///////////////////////////////////////////////////////////////+3leKCAAAAEHRSTlMA8DAQ0GBP4LCggMBwIJBAIttdjAAAAINJREFUOMvdkUsOwyAMBbH5hUCauf9pK1SlohF438x2LPn52f09+8vUfiNb/gighj8FouEjYCUoQDXiBSD7pdcMiK7XC9wCFmlDO3T20Scgx287ne13pwDU89NOJ3g3maCmJDANqIGRtLj8oi1ed1GMdmcB7wXIYX8QdQZJiM5Em3smbyVICDCOrCqSAAAAAElFTkSuQmCC") no-repeat;
  48. background-size: 100%; }
  49. .toast_error {
  50. background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAAMFBMVEUAAAD///////////////////////////////////////////////////////////87TQQwAAAAD3RSTlMA0BDAMODwUKBgsCCAQJClzVPvAAAA0UlEQVQoz2MgErAclv9o44Dgc8b/B4KvBTA+t/3XdgeWivjPG6ACbl8ngNXlp0AN+L8IwtD6DzFm2w+Y3v5sMGW/ACbA9Rms9ZsCTIApH2QR608GhoUKQJ4xA8P8AKCAP5CwF2JgUPwIlPwCFDj/AMRRYJIHCnL8AZkJ1AfkAcUYGNhBpso7MICUgBQw8H4EEv/B5ssDFYA4mAKYWjANfd+Aai3CYZ9BDoM63RDkdEGQ0zE9h+l9zADCDEIGt2/wQEZEwwVepGhgYEdEFGZUEgYAW05XI3jSsVwAAAAASUVORK5CYII=") no-repeat;
  51. background-size: 100%; }
  52. .toast_info {
  53. background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAALVBMVEUAAAD///////////////////////////////////////////////////////+hSKubAAAADnRSTlMA4CCAwKBAMJBg8NAQUNhWlbcAAAC+SURBVCjPYyASsLfse+1cgOBzyr0DgocXYHwmv4dtCkwZck8UoAJZDydA1C2H8NnexUAYR99BjNF6CtMbtwhM+QUACUUhIMH6BKz14QEgafcYSPDIgSxifMkAE2CYJwAk6gQQAozPgURfA0KAA0T6JSAE2ECm7lNACDC9BhLvGGACIA6GAFyLohBEC9xQqLeeQKwFA4i1EIfBAeNzuNMVhSBOx/AcpvcxAwgzCDEDGTMaGHhhEYWIShN4VBIGAPvRT5YzufhUAAAAAElFTkSuQmCC") no-repeat;
  54. background-size: 100%; }
  55.  
  56. @-webkit-keyframes loading {
  57. 0% {
  58. -webkit-transform: rotate3d(0, 0, 1, 0deg);
  59. transform: rotate3d(0, 0, 1, 0deg); }
  60. 100% {
  61. -webkit-transform: rotate3d(0, 0, 1, 360deg);
  62. transform: rotate3d(0, 0, 1, 360deg); } }
  63.  
  64. @keyframes loading {
  65. 0% {
  66. -webkit-transform: rotate3d(0, 0, 1, 0deg);
  67. transform: rotate3d(0, 0, 1, 0deg); }
  68. 100% {
  69. -webkit-transform: rotate3d(0, 0, 1, 360deg);
  70. transform: rotate3d(0, 0, 1, 360deg); } }

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

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号