layout: post
title: React全局消息组件
date: 2019-10-06
author: 霁
header-img:
catalog: true
categories:
为了在项目里构建一个能够使用的全局消息组件,以达到反馈。
参考连接:
消息不需要一直存在于页面中。
主要是在需要的时候往页面中插入一个div
,
再利用ReactDOM
添加一个组件容器 Notification
。
使用createRef()
创建一个ref
以获取这个实例引用。
进行容器里的添加消息或者移除消息。
一个Toast模块:
index.js
: 暴露出 Toast
Notification.jsx
: 生成一个容器toast.css
:样式需要一个数组进行保存:notices:[]
一个notice
需要的东西:
notice:{
type,//类型:[info|success|error|warning]
text,//消息文本
onClose,//消失的回调函数
duration,//显示的时长
}
react版本:
"react": "^16.10.2",
"react-dom": "^16.10.2",
"react-infinite-scroller": "^1.2.4",
"react-scripts": "3.2.0"
文件目录结构:
import React,{Component} from 'react'
import ReactDOM from 'react-dom'
import './toast.css';
class Notification extends Component {
constructor(){
super();
//设置回调函数的执行
this.transitionTime = 300;
this.state = {
notices:[]
}
}
// 使用时间和数组长度以保证唯一性
getNoticeKey = ()=>{
return `notice:${new Date().getTime()}:${this.state.notices.length}`;
}
addNotice = (notice) =>{
// 创造一个不重复的key
const {notices} = this.state;
const key = notice.key ? notice.key : notice.key = this.getNoticeKey();
const temp = notices.filter((item) => item.key === key).length;
if(!temp){
// 不存在重复的 添加
notices.push(notice);
this.setState({
notices,
})
}
console.log(notice)
if (notice.duration > 0) {
setTimeout(() => {
this.removeNotice(notice.key)
}, notice.duration);
}
}
removeNotice = (key)=>{
let {notices} = this.state;
notices = notices.filter((item)=>{
if (item.key === key) {
if (item.onClose) {
setTimeout(item.onClose(),this.transitionTime)
}
return false
}
return true
})
this.setState({
notices
})
}
render(){
const { notices } = this.state
return (
// 当长度为0时不渲染容器
notices.length >0 ?
<div className="toast">
{notices.map(item=>(
<div className={`toast-inner ${item.type}`} key={item.key}>
{/* <span className={item.type}></span> */}
<p className="toast-text">{item.text}</p>
</div>
))}
</div>:''
)
}
}
// 生成一个容器 DOM 并返回创建和销毁方法。
function createNotification(){
const div = document.createElement('div');
document.body.appendChild(div)
const ref = React.createRef()
ReactDOM.render(<Notification ref={ref}/>,div)
return{
add(notice){return ref.current.addNotice(notice)},
destroy(){
ReactDOM.unmountComponentAtNode(div)
document.body.removeChild(div)
}
}
}
export default createNotification()
上述的重点是利用 createNotification(),生成返回一个对象。
在index.js还需要判断页面内这个对象是否存在,存在就使用这个对象。
import Notification from './Notification';
let toast
// 将回调函数参数放置于带有默认参数的duration 前
// 可以在使用的时候避免设置回调同时需要指定时长的问题
// 原因是es6在要跳过一个带有默认参数的时候必须指定其值或者为undefined
const notice = (type,text,onClose,duration=2000,) =>{
// 防止生成多个容器
if (!toast) {
toast = Notification
}
console.log(duration)
if(!text){
return;
}else{
text = text.toString();
// 添加一个消息
return toast.add({
type,
text,
onClose,
duration,
})
}
}
// 未引入配置方法
export default {
info:(text,onClose,duration)=>notice('info',text,onClose,duration),
success:(text,onClose,duration)=>notice('success',text,onClose,duration),
error:(text,onClose,duration)=>notice('error',text,onClose,duration),
warning:(text,onClose,duration)=>notice('warning',text,onClose,duration),
hide:()=>{if(toast){ return toast.destroy()}},
}
问题:在使用的时候设置回调必须同时需要指定时长的问题?
原因:是es6在要跳过一个带有默认参数的时候必须指定其值或者为undefined
未引入图标
.toast {
position: fixed;
right:15px;
top:20%;
z-index: 999;
display: flex;
display: -webkit-flex;
flex-direction: column;
justify-content: center;
}
.toast-inner {
background: #FFFFFF;
padding: 16px 32px;
box-shadow: 0px 10px 20px 0px rgba(0, 0, 0, .1);
border-radius: 4px;
color: #454545;
font-size: 15px;
align-items: center;
position: relative;
margin-bottom: 20px;
}
.info{
background: #86e7f8da;
border-left:5px solid #5dcde0da;
}
.success{
background: #86f899da;
border-left:5px solid #54d699da;
}
.error{
background: #974154da;
border-left:5px solid #e02c2cda;
}
.warning{
background: #dddb63da;
border-left:5px solid #c7a740da;
}
<button onClick ={()=>Toast.hide()}>des</button>
在需要的地方引入该模块Toast
比如我在负责请求和相应的模块里使用来提示交互消息
// 引入
import Toast from '../components/Toast';
// 使用
时长默认2000可以写也可以不写。
Toas.info('请求Loding',()=>console.log("请求Loading消失的回调函数"),3000)
其他的类似。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。