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;
}
}``