前言:很多toast的库不是自己理想的,也不太好看,下面封装一个TypeScript的Toast组件
先看效果: 组件源码贴到下面,可以随便修改成自己想要的样子
Toast.tsx:
import React, { useState, useEffect, useRef, forwardRef, useImperativeHandle, Ref } from 'react';
import './index.scss';
import ReactDOM from 'react-dom';
interface ToastProps {
widthStyle?: any;
contentText?: string | null;
containerEl?: any;
}
export interface ToastType {
show: (text: string) => void;
}
const Toast = forwardRef((props: ToastProps, ref: Ref<ToastType>): any => {
const ToastRef: React.RefObject<HTMLDivElement> = useRef(null);
const [showToast, setShowToast] = useState<boolean>(false);
const [fadeIn, setFadeIn] = useState<boolean>(false);
const [contentText, setContentText] = useState<string>('');
useImperativeHandle(ref, () => ({
show: (text: string) => show(text),
}));
useEffect(() => {
if (!showToast) return;
const id = setTimeout(() => {
setFadeIn(false);
}, 2500);
return () => clearTimeout(id);
}, [showToast]);
useEffect(() => {
if (fadeIn || !showToast) return;
const id = setTimeout(() => {
setShowToast(false);
}, 500);
return () => clearTimeout(id);
}, [fadeIn, showToast]);
useEffect(() => {
if (!('contentText' in props)) return;
if (props.contentText) {
setContentText(props.contentText || '');
setFadeIn(true);
setShowToast(true);
} else if ('contentText' in props && props.contentText === null) {
setFadeIn(false);
setShowToast(false);
}
}, [props]);
const show = (text: string) => {
if (showToast) return;
setContentText(text);
setFadeIn(true);
setShowToast(true);
};
return ReactDOM.createPortal(
<div
ref={ToastRef}
className={`toast ${fadeIn ? `fadeIn` : `fadeOut`}`}
style={{ display: showToast ? 'block' : 'none', ...props.widthStyle }}
>
<div className='toastInner'>
<i className='icon'></i>
<div className='content'>
<span>{contentText}</span>
</div>
</div>
</div>,
props.containerEl || document.getElementById('wbContentContainer') || document.body,
);
})
Toast.displayName = 'Toast';
export default Toast;
index.scss:
.toast {
position: absolute;
top: 50%;
left: 50%;
z-index: 999999;
display: none;
transform: translate(-50%, -50%);
&.fadeIn {
animation: keyframes-fadeIn 0.5s forwards;
}
&.fadeOut {
animation: keyframes-fadeOut 0.5s forwards;
}
.toastInner {
position: relative;
width: auto;
max-width: 450px;
min-height: 40px;
padding: 0 18px 0 40px;
background: rgba(0, 0, 0, 0.8);
border-radius: 8px;
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.25);
display: flex;
align-items: center;
.icon {
position: absolute;
bottom: 0;
left: 18px;
top: 12px;
width: 16px;
height: 16px;
margin-right: 4px;
background-image: url("写你的icon图片路径");
background-position: 0 0;
background-size: cover;
}
.content {
color: #fff;
padding: 8px 0;
span {
display: -webkit-box;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #F46C60;
}
}
}
}
@keyframes keyframes-fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes keyframes-fadeOut {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
如何使用呢?
第一步在组件引入Toast:
import Toast from '@/components/Toast'; // 上面的Toast.tsx文件
第二步:放到dom里
<Toast ref={ToastRef}></Toast>
第三步:定义一个ToastRef的ref对象用于控制显隐
const ToastRef: any = useRef(null);
第四步:使用它
ToastRef.current?.show('小芳学前端')
最后显示效果就是这样子的,2500ms之后消失
添加好友备注【进阶学习】拉你进技术交流群