1. 动画组件
原理: 利用transition和class类的切换执行transition的动画效果
import React, { useEffect } from "react";
import _ from "lodash";interface IProps {name: string;children: React.ReactNode;transitionShow: boolean;
}
sessionStorage.transitionObject = JSON.stringify({});
const MyTransition = (props: IProps) => {const { name, children, transitionShow } = props;const popClass = React.useRef<any>(JSON.parse(sessionStorage.transitionObject));function orignalSetItem(key, newValue) {sessionStorage.setItem(key, newValue);// var setItemEvent:any = new Event("setItemEvent");// setItemEvent['newValue'] = newValue;// window.dispatchEvent(setItemEvent);}const showTransition = (name, transitionShow = true) => {const val = transitionShow ? "-leave-active" : "-leave-to";let obj = JSON.parse(sessionStorage.transitionObject) || {};obj[name] = name + val;for (let key in obj) {obj[key] = key + val;}orignalSetItem("transitionObject", JSON.stringify(obj));};const getTransition = (name, transitionShow = true) => {const val = transitionShow ? "-leave-active" : "-leave-to";popClass.current[name] = val;let obj = JSON.parse(sessionStorage.transitionObject) || {};obj[name] = name + val;for (let key in obj) {obj[key] = key + val;popClass.current[key] = key + val;}return _.get(obj, name);};useEffect(() => {showTransition(name, transitionShow);}, [transitionShow]);return <div className={getTransition(name, transitionShow)}>{children}</div>;
};export default MyTransition;
scss部分:
// transition动画部分.myOpacity-enter,.myOpacity-leave-to {opacity: 0;}.myOpacity-enter-active,.myOpacity-leave-active {transition: all 0.5s ease;}.myPopup-enter,.myPopup-leave-to {transform: translateY(100px);}.myPopup-enter-active,.myPopup-leave-active {transition: all 0.5s ease;}
使用方法, 比如一个modal组件需要动画的话:
import React, { useEffect, useState, ReactNode, useImperativeHandle, forwardRef } from "react";
import _ from "lodash";
import "./Picker.scss";
import * as ReactDOM from "react-dom";
import MyTransition from "./MyTransition";interface IProps {isShow: boolean;setIsShow: (arg1: boolean) => void;children: ReactNode;
}const MyPickerModal = forwardRef((props: IProps, ref) => {const { isShow, setIsShow, children } = props; // 解构props, 得到需要使用来自父页面传入的数据const [pickerIsShow, setPickerIsShow] = useState(props.isShow);useEffect(() => {setPickerIsShow(isShow);}, [isShow]);useImperativeHandle(ref, () => ({close,}))function close() {setTimeout(() => {setPickerIsShow(false);// 延迟关闭, 因为MyTransition需要这段时间差执行动画效果, 否则看起来像没有动画效果似的突然消失了setTimeout(() => {setIsShow(false);}, 500);}, 0);} // 点击取消按钮return ReactDOM.createPortal(<div className="picker-container"><MyTransition name="myPopup" transitionShow={pickerIsShow}>{isShow && <section className="pop-cover" onClick={close}></section>}</MyTransition><MyTransition name="myOpacity" transitionShow={pickerIsShow}>{isShow && children}</MyTransition></div>,document.body);
});export default MyPickerModal;
ReactDOM.createPortal(element, 要插入这个elment的父元素, 一般写body, 也自己去html文件加一个元素, 插入到那个元素中去