totast
最近在主导有 jquery 类型转 react 技术栈 – 项目库中引入 antd-mobile,
但是由于 totast 组件不能满足要求 … 自己前端封装一个。(其实我很菜)
重要点:
1. 分什么技术栈,全是垃圾,真正掌握基础,啥库都是渣渣,框架也是库,也是渣渣。
2. 大家有没有发现 – 一些 dialog 组件 和 totast 组件,他们一般都会脱离当前渲染 ui 层级,
单独的插入到 body 的下面第一级的 child 节点, 猜想目的:
(1)这类型的组件,应该是单独的根,不应该和现有渲染的组件嵌套,与现有业务分离。
(2)把元素直接查入到,非 body 的第一级 child 节点,当移动端渲染的时候,fixed 定位,会造成子元素渲染高度存在问题实例, 之前开发遇到过。
/ 代码 /
import React from 'react';
import ReactDom from 'react-dom';
import ToastCmp from './ToastCmp';
const win = window;
const doc = win.document;
let layoutIndex = 999;
// 基础函数
const jcToastCmp = ({message, time = 2000, zIndex, warpClass, amName = 'fade-in', loc}) => {
// 生成待插入 totast 组件 的 dom 容器
const div = doc.createElement('div');
div.setAttribute('id', `custom-totastcomp-${layoutIndex}`);
// 拿到组件实例
const compRef = React.createRef();
doc.body.appendChild(div);
// 关闭组件
const close = () => {
// 调用组件替换过渡动画的 Class 从而产生过渡动画,然后触发过渡动画钩子
compRef.current.toggleAmClass(amName);
};
const removeDiv = () => {ReactDom.unmountComponentAtNode(div);
doc.body.removeChild(div);
};
// 存在倒计时,会自动删除组件
time && setTimeout(close, time);
// 渲染 totast
ReactDom.render(<ToastCmp
warpClass={warpClass}
amName={amName}
message={message}
ref={compRef}
amLevelHook={removeDiv}
zIndex={zIndex || layoutIndex}
loc={loc}
/>, div);
!zIndex && layoutIndex++;
// 返回删除方法
return {close,};
};
// 成功方法调用
jcToastCmp.success = ({message, time, zIndex, amName, loc}) => {
return jcToastCmp({
message,
time,
zIndex,
warpClass: 'totast-success',
amName,
loc,
});
};
/// 警告方法调用
jcToastCmp.warn = ({message, time, zIndex, amName, loc}) => {
return jcToastCmp({
message,
time,
zIndex,
warpClass: 'totast-warn',
amName,
loc,
});
};
export default jcToastCmp
===
ToastCmp
import React from 'react';
import PropsType from 'prop-types';
import './index.less';
const defaultClassName = 'custom-totast-cmp';
class ToastCmp extends React.PureComponent {
static propsType = {
warpClass: PropsType.string,
amLevelHook: PropsType.func.isRequired, // 元素离开视口所触发的钩子
loc: PropsType.string, // totast 显示的位置
}
static defaultProps = {
warpClass: '',
loc: 'top',
}
state = {className: '',}
amState = 0
constructor(props) {super(props);
const {warpClass, loc} = props;
const initClassName = `${defaultClassName} ${warpClass} totast-${loc}`;
this.state.defaultClassName = initClassName;
this.state.className = initClassName;
}
// 交互替换过渡动画 class 名字
toggleAmClass = (amName) => {const {state, amState} = this;
const {defaultClassName} = state;
if (amState === 0) {
this.setState({className: `${defaultClassName} ${amName}`,
});
} else {
this.setState({className: defaultClassName,});
}
}
// 动画类开钩子
amLevelHook = () => {const {props, amState} = this;
if (amState !== 0) {const { amLevelHook} = props;
amLevelHook();}
this.amState++;
}
componentDidMount() {const {toggleAmClass, props} = this;
const {amName} = props;
// 延迟 产生进入过渡动画
setTimeout(toggleAmClass, 50, amName);
}
render() {const {props, state, amLevelHook} = this;
const {className} = state;
const {message, zIndex} = props;
const style = {zIndex,};
return (
<div
className={className}
onTransitionEnd={amLevelHook}
style={style}
>
{message}
</div>
);
}
}
export default ToastCmp;
index.less
.custom-totast-cmp {
position: fixed;
left: 50%;
transform: translate(-50%, 0);
padding: pxToRem(5px) pxToRem(30px);
background: #333;
color: #fff;
opacity: 0;
transition: opacity 500ms ease;
border-radius: 4px;
text-align: center;
&.totast-top {top: 0;}
&.totast-middle {
top: 50%;
transform: translate(-50%, -50%);
}
&.totast-success {
color: #fff;
background: @success-color; // 成功提示色
}
&.totast-warn {
color: #fff;
background: @warn-color; // 失败提示色
}
&.fade-in {opacity: 1;}
}``