一、react-transition-group 使用
相关技术的使用:
- React 18
- React router v6
React Transition Group 是一个 React 库,专门用于在 React 应用中管理和处理过渡动画效果。这个库提供了一组组件,包括 Transition、CSSTransition、SwitchTransition 和 TransitionGroup,帮助在组件的进入和退出时应用动画效果。
Transition 是一个与平台无关的组件,通常结合 CSS 完成样式。
CSSTransition 是一个常用的组件,广泛用于添加过渡动画效果。它具有动画的作用时间(timeout)和指定元素首次渲染在页面时是否进行动画(appear)等参数。
SwitchTransition 用于在两个组件显示和隐藏切换时使用。
TransitionGroup 将多个动画组件包裹在其中,一般用于列表中元素的动画。执行中有三个状态:appear,enter,exit,这需要定义对应的 CSS 样式。
React Transition Group 可以应对大量常见简单动画,但如果需要编写高级动画,建议使用其他库如 react-spring、framer-motion 等。
Layout的示例伪代码
import { CSSTransition, SwitchTransition } from 'react-transition-group';
import { useLocation, useNavigate, useOutlet } from 'react-router-dom';
const currentOutlet = useOutlet();
...
<Layout className="site-layout">
<Content className="site-content">
<SwitchTransition mode="out-in">
<CSSTransition
key={location.pathname}
appear={true}
timeout={300}
classNames="page"
unmountOnExit
>
{currentOutlet}
</CSSTransition>
</SwitchTransition>
</Content>
</Layout>
因为 CSSTransition 的 classNames 为 page:
// 页面切换过渡动画
.page {
position: absolute;
left: 15px;
right: 15px;
}
// 页面切换过渡动画 --- 进入
.page-enter {
opacity: 0;
transform: scale(1.1);
}
// 页面切换过渡动画 --- 进入(被激活)
.page-enter-active {
opacity: 1;
transform: scale(1);
transition: opacity 300ms, transform 300ms;
}
// 页面切换过渡动画 --- 离开
.page-exit {
opacity: 1;
transform: scale(1);
}
// 页面切换过渡动画 --- 离开(被激活)
.page-exit-active {
opacity: 0;
transform: scale(0.9);
transition: opacity 300ms, transform 300ms;
}
注意事项:
1.网上可以搜到的许多文章里都提到,组件间的切换动画需要使用 TransitionGroup 来包裹。但是在官网最新的介绍里可以看到这段话
- 第一反应可能是在 TransitionGroup 中包裹所有路由,但这种方法需要 hack 并且在与 React Router 的更棘手的组件(如 Redirect)一起使用时很容易崩溃。 您应该为每个路由使用 CSSTransition 并自行在prop中管理它们。”
2.使用 SwitchTransition 包裹 CSSTransition,这样不会导致页面上同时展示 A 页面和 B 页面的组件,反之使用 TransitionGroup 进行包裹,就会产生两个页面同时存在的情况。
3.最重要的一点: 不要直接使用 Outlet 及<Outlet />
,而要使用useOutlet。在我没阅读官网的代码前,我尝试使用 SwitchTransition 和 CSSTransition 对 <Outlet />
进行包裹,来实现子路由组件的展示。结果:
- 第一个页面的离开的动画丢失了。
- 第二个页面会被加载两次,直观反映就是页面闪烁,
useEffect(()=>{},[])
或者componentDidMount()
被调用两次。
因为<Outlet />
会导致在同一页面的新旧组件各调用一次接口,所以请使用 useOutlet。
二、 <Outlet />
与 useOutlet 区别
<Outlet />
和useOutlet
都是在React Router中用来实现路由导出的功能,但是它们的使用方式和场景有所不同。
<Outlet />
:
<Outlet />
是一个 React 组件,通常在路由配置中使用,用于指定当前路由的子组件应该被渲染到哪个位置。它是一个受控组件,也就是说,它的值(即要渲染的组件)是由父组件(通常是路由组件)控制的。当父组件的状态发生改变时,<Outlet />
会自动更新渲染的组件。
例如,在路由配置中,你可以使用<Outlet />
来指定一个位置,用于渲染当前路由的子路由组件:
<Route path="/user/:userId" component={UserPage}>
<Outlet />
</Route>
在上面的例子中,当用户访问一个符合 /user/:userId
路径的URL时,UserPage组件会被渲染,并且子路由组件会渲染到 <Outlet />
指定的位置。
useOutlet
:
useOutlet
是一个自定义Hook,它允许你在函数组件中使用React Router的功能。通过使用 useOutlet
,你可以在组件中获取到当前路由的子路由组件,并将其渲染到指定的位置。与 <Outlet />
不同的是,useOutlet
是一个非受控组件,它的值是由调用 Hook 的代码控制的。useOutlet
是一个钩子函数,它用于在组件中获取当前嵌套路由的信息。如果嵌套路由没有挂载,则 useOutlet
返回 null;如果嵌套路由已经挂载,则 useOutlet
返回嵌套的路由对象。通过使用 useOutlet
,可以在组件中获取嵌套路由的相关信息,例如路径、查询参数等。
下面是使用 useOutlet
的示例:
import { useOutlet } from 'react-router-dom';
function MyComponent() {
const outlet = useOutlet();
return (
<div>
<h1>My Component</h1>
{outlet}
</div>
);
}
在上面的例子中,我们通过使用useOutlet
获取到一个outlet
对象,然后将这个对象渲染到组件中指定的位置。当路由发生变化时,React Router会自动更新渲染的子路由组件。
总的来说,<Outlet />
和 useOutlet
在 React Router v6 中都用于处理嵌套路由的相关操作。<Outlet />
更适合在 React Router 的路由配置中使用,用于在应用程序的当前路由中渲染嵌套的 Route 组件。而 useOutlet
则更适合在函数组件内部使用,用于在组件中获取当前嵌套路由的信息。
1.本站内容仅供参考,不作为任何法律依据。用户在使用本站内容时,应自行判断其真实性、准确性和完整性,并承担相应风险。
2.本站部分内容来源于互联网,仅用于交流学习研究知识,若侵犯了您的合法权益,请及时邮件或站内私信与本站联系,我们将尽快予以处理。
3.本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
4.根据《计算机软件保护条例》第十七条规定“为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。”您需知晓本站所有内容资源均来源于网络,仅供用户交流学习与研究使用,版权归属原版权方所有,版权争议与本站无关,用户本人下载后不能用作商业或非法用途,需在24个小时之内从您的电脑中彻底删除上述内容,否则后果均由用户承担责任;如果您访问和下载此文件,表示您同意只将此文件用于参考、学习而非其他用途,否则一切后果请您自行承担,如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
5.本站是非经营性个人站点,所有软件信息均来自网络,所有资源仅供学习参考研究目的,并不贩卖软件,不存在任何商业目的及用途
暂无评论内容