内容简介:很多项目中需要实现app中常见的提示效果Toast。这个效果看似简单,实现起来也容易,为了方便,将它封装成npm组件,方便后续使用。 这里也是抛砖引玉,可以查看项目地址一起学习Notification是个容器,里面有一个notice数组。 然后render的时候,循环notices生成一段DOM节点,放到自己的div中。 同时,其还提供一个向notices中添加notice的方法(add)和根据key,在notices中删除notice的方法(remove)。 最后关键的地方,定义一个reRwrite方法,
很多项目中需要实现app中常见的提示效果Toast。这个效果看似简单,实现起来也容易,为了方便,将它封装成npm组件,方便后续使用。 这里也是抛砖引玉,可以查看项目地址一起学习 react-comment-toast
使用方法
import Toast from "react-common-toast";
Toast.info("xxx");
Toast.info("xxx",duration,onClose);
复制代码
组件拆分
- 首先是支持多个提示,不同提示定制化也可以不同。取名为Notice。
- Notice外面还有个容器组件,用来装载Notice并且,暴露一些方法给Toast,起名Notification,是一个单例。
- 最后就是Toast组件,负责直接生成不同的Notice,或者销毁Notification。但是其实Toast只是个对象,而不是真正意义的组件。
Notification
Notification是个容器,里面有一个notice数组。 然后render的时候,循环notices生成一段DOM节点,放到自己的div中。 同时,其还提供一个向notices中添加notice的方法(add)和根据key,在notices中删除notice的方法(remove)。 最后关键的地方,定义一个reRwrite方法,该方法接受一些参数,动态的向DOM中插入一个div,然后再向这个div中插入Notification,最后返回一个含有几个操作这个Notification的方法的对象。(这就是动态实现插入DOM的关键)
// Notification是Notice父组件,容器
// 是动态插入和删除DOM节点的核心
// 同时也向上暴露给Toast重写改变自己的方法
import React from "react";
import ReactDOM from "react-dom";
import Notice from "./Notice";
import "./toast.css";
// 统计notice总数 防止重复
let noticeNumber = 0;
// 生成唯一的id
const getUuid = () => {
return "notification-" + new Date().getTime() + "-" + noticeNumber++;
};
export default class Notification extends React.Component {
constructor(props) {
super(props);
this.state = {
notices: [], // 存储当前有的notices
hasMask: true // 是否显示蒙版
};
}
add(notice) {
// 添加notice
// 创造一个不重复的key
const { notices } = this.state;
const key = notice.key ? notice.key : (notice.key = getUuid());
const mask = notice.mask ? notice.mask : false;
const temp = notices.filter(item => item.key === key).length;
if (!temp) {
// 不存在重复的 添加
notices.push(notice);
this.setState({
notices: notices,
hasMask: mask
});
}
}
remove(key) {
// 根据key删除对应
this.setState(previousState => {
return {
notices: previousState.notices.filter(notice => notice.key !== key)
};
});
}
getNoticeDOM() {
const _this = this;
const { notices } = this.state;
let result = [];
notices.map(notice => {
// 每个Notice onClose的时候 删除掉notices中对应key的notice
const closeCallback = () => {
_this.remove(notice.key);
// 如果有用户传入的onClose 执行
if (notice.onClose) notice.onClose();
};
result.push(
<Notice key={notice.key} {...notice} onClose={closeCallback} />
);
});
return result;
}
getMaskDOM() {
const { notices, hasMask } = this.state;
// notices为空的时候 不显示蒙版
// 始终只有一个蒙版
if (notices.length > 0 && hasMask == true)
return <div className="tips-mask" />;
}
render() {
const noticesDOM = this.getNoticeDOM();
//暂时没有配置蒙版
const maskDOM = this.getMaskDOM();
return (
<div>
{/*{maskDOM}*/}
{noticesDOM}
</div>
);
}
}
// Notification增加一个重写方法
// 该方法方便Notification组件动态添加到页面中和重写
Notification.reWrite = properties => {
const { ...props } = properties || {};
let div = document.createElement("div");
document.body.appendChild(div);
const notification = ReactDOM.render(<Notification {...props} />, div);
return {
notice(noticeProps) {
notification.add(noticeProps);
},
removeNotice(key) {
notification.remove(key);
},
destroy() {
ReactDOM.unmountComponentAtNode(div);
document.body.removeChild(div);
},
component: notification
};
};
复制代码
Notice
主要是负责接受一些参数,duration,icon,content等等
// Notice是Toast最底层组件
// 每个toast的小框框其实都是一个Notice
// Notice核心就是组件初始化的时候 生成一个定时器
// 根据输入的时间 加载一个动画 然后执行输入的回调
// Notice的显示和隐藏收到父组件Notification的绝对控制
import React from "react";
import classNames from "classnames";
import { PropTypes } from "prop-types";
export default class Notice extends React.Component {
constructor(props) {
super(props);
this.state = {
shouldClose: false // 是否开启关闭动画
};
}
componentDidMount() {
if (this.props.duration > 0) {
this.closeTimer = setTimeout(() => {
this.close();
}, this.props.duration - 300); // 减掉消失动画300毫秒
}
}
componentWillUnmount() {
// 当有意外关闭的时候 清掉定时器
this.clearCloseTimer();
}
clearCloseTimer() {
if (this.closeTimer) {
clearTimeout(this.closeTimer);
this.closeTimer = null;
}
}
close() {
// 关闭的时候 应该先清掉倒数定时器
// 然后开启过场动画
// 等待动画结束 执行回调
this.clearCloseTimer();
const _this = this;
_this.setState({ shouldClose: true });
this.timer = setTimeout(() => {
if (this.props.onClose) {
this.props.onClose();
}
clearTimeout(_this.timer);
}, 300);
}
render() {
const { shouldClose } = this.state;
return <div className={classNames({ leave: shouldClose })}>
{this.props.content}
</div>
}
}
Notice.propTypes = {
duration: PropTypes.number, // Notice显示时间
content: PropTypes.any, // Notice显示的内容
onClose: PropTypes.func // 显示结束回调
};
Notice.defaultProps = {
duration: 3000
};
复制代码
Toast
Toast首先就是要利用Notification.reWrite初始化一个newNotification,并且保持这个Notification为单例。 然后封装一个notice方法,动态的改变这个newNotification。 最后封装几个常用notice方法暴露出去。
import React from "react";
import classNames from "classnames";
import Notification from "./Notification";
// Toast组件比较特殊
// 因为<Toast />不会被直接渲染在DOM中
// 而是动态插入页面中
// Toast组件核心就是通过Notification暴露的重写方法 动态改变Notification
let newNotification;
// 获得一个Notification
const getNewNotification = () => {
// 单例 保持页面始终只有一个Notification
if (!newNotification) {
newNotification = Notification.reWrite();
}
return newNotification;
};
// notice方法实际上就是集合参数 完成对Notification的改变
const notice = (content, type, duration = 3000, onClose, mask = true) => {
if (!content) return;
// content = content.toString();
let notificationInstance = getNewNotification();
notificationInstance.notice({
duration,
mask: mask,
content: (
<div className={classNames(["tips-notice-box"])}>
<div
className={classNames([
"tips-notice-content",
{ info: type === "info" },
{ success: type === "success" },
{ warning: type === "warning" },
{ error: type === "error" }
])}
>
{content}
</div>
</div>
),
onClose: () => {
if (onClose) onClose();
}
});
};
export default {
show(content, duration, icon, mask, onClose) {
return notice(content, undefined, icon, duration, onClose, mask);
},
info(content, duration, icon, mask, onClose) {
return notice(content, "info", icon, duration, onClose, mask);
},
success(content, duration, icon, mask, onClose) {
return notice(content, "success", icon, duration, onClose, mask);
},
warning(content, duration, icon, mask, onClose) {
return notice(content, "warning", icon, duration, onClose, mask);
},
error(content, duration, icon, mask, onClose) {
return notice(content, "error", icon, duration, onClose, mask);
},
hide() {
if (newNotification) {
newNotification.destroy();
newNotification = null;
}
}
};
复制代码
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- php如何实现session,自己实现session,laravel如何实现session
- AOP如何实现及实现原理
- webpack 实现 HMR 及其实现原理
- Docker实现原理之 - OverlayFS实现原理
- 为什么实现 .NET 的 ICollection 集合时需要实现 SyncRoot 属性?如何正确实现这个属性?
- 自己实现集合框架(十):顺序栈的实现
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
神经网络与机器学习(原书第3版)
[加] Simon Haykin / 申富饶、徐烨、郑俊、晁静 / 机械工业出版社 / 2011-3 / 79.00元
神经网络是计算智能和机器学习的重要分支,在诸多领域都取得了很大的成功。在众多神经网络著作中,影响最为广泛的是Simon Haykin的《神经网络原理》(第3版更名为《神经网络与机器学习》)。在本书中,作者结合近年来神经网络和机器学习的最新进展,从理论和实际应用出发,全面、系统地介绍了神经网络的基本模型、方法和技术,并将神经网络和机器学习有机地结合在一起。 本书不但注重对数学分析方法和理论的探......一起来看看 《神经网络与机器学习(原书第3版)》 这本书的介绍吧!