基于react-router-dom, view transition 实现路由切换过渡动效

基于react-router-dom, view transition 实现路由切换过渡动效

可以先看看效果以及代码

view-transition-demo.yangbingrui.info/

背景

在我之前的文章提到,用了 framer-motion 这个包来实现了路由切换时的过渡动效。

关于用 framer-motion来实现路由切换动效的文章

其中一个 hack 写法用于实现前路由离开时的动效,大概是这样的

jsx 复制代码
export const AnimatedOutlet = ({ OutletContext } = {}) => {
    const location = useLocation();
    const element = useOutlet(OutletContext);
    return (
        <AnimatePresence
            mode="wait"
            initial={true}
        >
            {element && React.cloneElement(element, { key: location.pathname })}
        </AnimatePresence>
    );
};

但是这个写法会导致一些副作用,例如,会导致我封装好的 table 组件里面的 hook 执行两次,猜测是在framer-motion库对路由切换时,会克隆一个前路由组件,再对其添加离开动效所导致的。

好的点是:

  • 动效流畅;
  • 兼容性好;

不好的点是:

  • 代码稍显复杂,其他同事难以维护;
  • 当存在a-b-c三级嵌套路由时,想往某个层级里添加过渡动效,都要往该层级嵌套AnimatePresence, motion.div,稍显麻烦。

虽说可以通过一些方式来避免这个副作用,但还是有点麻烦,于是在寻找替代方案。

解决方案

最近发现一个浏览器的特性 view-transition,可以轻松地给组件增加动效,而且基本只需要写 css 就行(并且也要给 react-router-dom 的Link配置viewTransition属性为 true)。于是我用这个特性来替换掉 frame-motion。

一些实现的细节

源码里面有些值得关注的细节:

  1. 注意这个 css 代码,其中的关键就是这几行,::view-transition-old 代表的是切换时,浏览器当前帧的节点离开时的动效声明,::view-transition-new 代表的是浏览器下一帧新的节点进入时的动效声明,b-page-transition是对应节点的 view-transition-name
css 复制代码
::view-transition-old(b-page-transition) {
  animation: var(--b-page-transition-duration) ease-in-out both
    b-page-transition-fade-out;
}

::view-transition-new(b-page-transition) {
  animation: var(--b-page-transition-duration) var(--b-page-transition-duration)
    ease-in-out both b-page-transition-fade-in;
}
  1. 注意这个写法
css 复制代码
.b-page:has(.c-page) {
  view-transition-name: none;
  animation: none;
}

之所以这样写,是因为切换 3 级路由时,不希望再触发 2 级路由的切换动效了,如果不这样写的话,那么切换时,2 、3 级的过渡动效都会被触发。

还有一个点,这里之所以不把 c-page 放到 3 级页面那一层级,之所以这样写,是为了避免首次从 2 级跳到 3 级路由时页面轻微的跳动。跳动的原因,我猜测是切换时 同时触发 2,3 级路由的动效,但又命中上面那条 css 规则所导致的吧。

jsx 复制代码
const BPage = () => {
    //...
      <div className="c-page">
        <Outlet />
      </div>
    //...
};

总结

于是我用了 view-transition 来代替了 framer-motion 来实现路由切换时的动效,效果还可以,还加上了之前不好 实现的 2 级路由切换动效,因为实际通过 framer-motion 来实现动效,要额外增加嵌套的层级深度。而使用了 view transition 这个特性,增加切换动效变得简单得多了。

相关推荐
SEO_juper1 分钟前
2026年用Python分析网站访问日志:看清Googlebot和AI爬虫怎么爬你的站(附完整代码)
开发语言·前端·seo·独立站·谷歌优化
摸鱼仙人~2 分钟前
React 原理进阶:彻底理解 re-render、React.memo、useMemo 与 useCallback
前端·vue.js
IMPYLH6 分钟前
HTML 的 <small> 元素
前端·网络·html
IT_陈寒7 分钟前
Vue的响应式让我加班到凌晨,问题竟出在这个不起眼的地方
前端·人工智能·后端
AlienZHOU9 小时前
AI Coding 时代下,我的技术面试实践分享
前端·后端·面试
Captaincc12 小时前
AI用量v0.1.11更新发布 新增 jusage doctor 诊断指令 托盘展示token 和余额 新增 AutoClaw 支持
前端·后端·vibecoding
计算机魔术师13 小时前
德国Wiki被黑后两周,OpenAI终于把模型失控的账本摊开了
前端
kyriewen14 小时前
我让 AI 当面试官面了我一轮:第 3 个追问我就卡住了(附 10 道追问清单)
前端·面试·ai编程
IT_陈寒14 小时前
Python的GIL把我坑惨了,多线程跑得比单线程还慢
前端·人工智能·后端
前端snow15 小时前
ai agent --- 多agent框架之图编排引擎-langgraph
前端