首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >React全局消息组件

React全局消息组件

原创
作者头像
我已经洗完澡了
修改2019-10-14 17:15:56
1.9K0
修改2019-10-14 17:15:56
举报

layout: post

title: React全局消息组件

date: 2019-10-06

author: 霁

header-img:

catalog: true

categories:

  • 学习
  • React tags:
  • React

需求

为了在项目里构建一个能够使用的全局消息组件,以达到反馈。

参考连接:

clancysong github

mobile ant design

uOtXB8.gif
uOtXB8.gif

开始

消息不需要一直存在于页面中。

主要是在需要的时候往页面中插入一个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"

文件目录结构:

  • Toast
    • index.js
    • Notification.jsx
    • toast.css
第一步:创建一个容器组件,包含notice的状态
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;
}
测试销毁div方法
  <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 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 需求
  • 开始
  • 拆分
  • 数据结构分析
  • 具体实现
    • 第一步:创建一个容器组件,包含notice的状态
      • 第二步:导出组件
        • 第三步样式
          • 测试销毁div方法
          • 具体使用
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档