TST*_*ias 5 javascript reactjs react-router-dom framer-motion
React Router v6.4 引入了带有createBrowserRouter和RouterProvider的新路由 API 。
在旧版本的 React Router 中,可以环绕使用 React Router 定义的路由以启用页面转换。当提供位置和关键点的值时,Framer Motion 可以检测是否在组件树中添加或删除了子组件以显示开始和退出过渡动画。
在 React Router v6.4 之前:
<AnimatePresence exitBeforeEnter>
<Routes location={location} key={location.pathname}>
<Route path="/" element={<HomePage />} />
</Routes>
</AnimatePresence>
Run Code Online (Sandbox Code Playgroud)
虽然页面加载时的动画仍然适用于新的路由 API,但我找不到让退出动画再次工作的方法。
反应路由器 v6.4.1
...
const router = createBrowserRouter([
{
path: '/',
element: (
<HomePage />
),
},
]);
...
<AnimatePresence mode="wait">
<RouterProvider router={router} />
</AnimatePresence>
Run Code Online (Sandbox Code Playgroud)
这是使用旧版本的 React Router 和 Framer Motion 的完整 React 应用程序的示例。
Rut*_*ula 11
对于没有嵌套路由的应用程序,您可以使用useOutlet解决此问题。
它应该位于包装其他路由的布局组件内,而不是包装 RouterProvider 的 AnimatePresence。
在您的路由器声明中,创建一个顶级布局组件,例如RootContainer。其余的路由可以使用 Children 属性声明,其中您的主页是索引路由:
const router = createBrowserRouter([
{
element: (
<RootContainer />
),
children: [
{
index: true,
element: <HomePage />,
},
...
]
},
]);
Run Code Online (Sandbox Code Playgroud)
在里面RootContainer你想要渲染一个 Outlet,它是一个将 UI 与当前路由匹配的组件。
要启用退出动画,我们需要使用“冻结”出口。这意味着每次位置发生变化时,插座参考保持不变。我们基本上将使用一个键来控制重新安装逻辑,类似于在 V5 实现中使用Routes. 有关解决方案的更多上下文以及为什么此类功能不是react-router-dom核心的一部分:https://github.com/remix-run/react-router/discussions/8008#discussioncomment-1280897
AnimatedOutlet:
const AnimatedOutlet: React.FC = () => {
const o = useOutlet();
const [outlet] = useState(o);
return <>{outlet}</>;
};
Run Code Online (Sandbox Code Playgroud)
在您的 中RootContainer,用运动组件包装 Outlet,并记住将当前路径名作为其键:
<AnimatePresence mode="popLayout">
<motion.div
key={location.pathname}
initial={{ opacity: 0, x: 50 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: 50 }}
>
<AnimatedOutlet />
</motion.div>
</AnimatePresence>
Run Code Online (Sandbox Code Playgroud)
不幸的是,对于具有许多嵌套路由的应用程序,此解决方案并不完全足够。在 V5 中,您可以通过使用位置“部分”来防止父路线在子路线导航期间重新渲染:
const location = useLocation()
const locationArr = location.pathname?.split('/') ?? [];
return
<Routes location={location} key={locationArr[1]}
...
<Routes location={location} key={locationArr[2]}
...
</Routes>
</Routes>
Run Code Online (Sandbox Code Playgroud)
我还不知道 useOutlet 是否可以实现这一点。
| 归档时间: |
|
| 查看次数: |
3893 次 |
| 最近记录: |