Astro 的视图转换(View Transitions)是一个强大的功能,可以实现类似单页应用(SPA)的平滑页面切换体验,同时保持静态站点的性能优势。
核心概念:
视图转换通过浏览器原生的 View Transitions API 实现,在页面导航时提供平滑的视觉过渡效果。
基本用法:
astro--- // src/layouts/Layout.astro import { ViewTransitions } from 'astro:transitions'; --- <html> <head> <title>我的网站</title> <ViewTransitions /> </head> <body> <slot /> </body> </html>
过渡效果类型:
-
淡入淡出(Fade):
astro<ViewTransitions transition="fade" /> -
滑动(Slide):
astro<ViewTransitions transition="slide" /> -
无过渡(None):
astro<ViewTransitions transition="none" />
自定义过渡效果:
astro--- // src/layouts/Layout.astro import { ViewTransitions } from 'astro:transitions'; --- <html> <head> <title>我的网站</title> <ViewTransitions /> <style is:global> ::view-transition-old(root), ::view-transition-new(root) { animation-duration: 0.5s; } @keyframes custom-fade { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } ::view-transition-new(root) { animation: custom-fade 0.5s ease-out; } </style> </head> <body> <slot /> </body> </html>
共享元素过渡:
astro--- // src/pages/index.astro import { transition } from 'astro:transitions'; --- <h1 transition:name="hero-title">欢迎来到我的网站</h1> <img src="/hero.jpg" alt="Hero Image" transition:name="hero-image" /> <a href="/about" transition:name="cta-button">了解更多</a>
astro--- // src/pages/about.astro import { transition } from 'astro:transitions'; --- <h1 transition:name="hero-title">关于我们</h1> <img src="/about.jpg" alt="About Image" transition:name="hero-image" /> <a href="/" transition:name="cta-button">返回首页</a>
编程式导航:
astro--- import { transition } from 'astro:transitions'; --- <button onClick={() => transition.navigate('/about')}> 关于我们 </button> <a href="/contact" data-astro-transition="fade"> 联系我们 </a>
高级配置:
astro--- // src/layouts/Layout.astro import { ViewTransitions } from 'astro:transitions'; --- <html> <head> <title>我的网站</title> <ViewTransitions /> </head> <body> <script> import { navigate } from 'astro:transitions/client'; // 监听导航事件 document.addEventListener('astro:page-load', () => { console.log('页面加载完成'); }); document.addEventListener('astro:after-preparation', () => { console.log('页面准备完成'); }); // 自定义导航 function customNavigate(url) { navigate(url, { history: 'push', state: { customData: 'value' }, }); } </script> <slot /> </body> </html>
条件过渡:
astro--- // src/layouts/Layout.astro import { ViewTransitions } from 'astro:transitions'; --- <html> <head> <title>我的网站</title> <ViewTransitions /> <script> // 只对特定链接应用过渡 document.querySelectorAll('a[href^="/blog/"]').forEach(link => { link.setAttribute('data-astro-transition', 'fade'); }); </script> </head> <body> <slot /> </body> </html>
与客户端组件集成:
jsx// src/components/Navigation.jsx import { useNavigate } from 'astro:transitions/client'; export function Navigation() { const navigate = useNavigate(); return ( <nav> <button onClick={() => navigate('/')}>首页</button> <button onClick={() => navigate('/about')}>关于</button> <button onClick={() => navigate('/contact')}>联系</button> </nav> ); }
性能优化:
-
预加载链接:
astro<a href="/about" data-astro-transition-prefetch> 关于我们 </a> -
禁用特定页面的过渡:
astro--- // src/pages/no-transition.astro --- <script> // 禁用视图转换 document.documentElement.dataset.astroTransition = 'false'; </script> <h1>这个页面没有过渡效果</h1> -
优化图片加载:
astro--- import { Image } from 'astro:assets'; import heroImage from '../assets/hero.jpg'; --- <Image src={heroImage} alt="Hero" transition:name="hero-image" loading="eager" />
事件监听:
astro--- // src/layouts/Layout.astro import { ViewTransitions } from 'astro:transitions'; --- <html> <head> <title>我的网站</title> <ViewTransitions /> </head> <body> <script> // 导航开始 document.addEventListener('astro:before-preparation', (ev) => { console.log('准备导航到:', ev.to.pathname); }); // 导航准备完成 document.addEventListener('astro:after-preparation', () => { console.log('导航准备完成'); }); // 页面开始加载 document.addEventListener('astro:before-swap', () => { console.log('开始替换页面'); }); // 页面加载完成 document.addEventListener('astro:page-load', () => { console.log('页面加载完成'); // 重新初始化客户端组件 initClientComponents(); }); // 导航错误 document.addEventListener('astro:after-swap', (ev) => { if (ev.detail?.error) { console.error('导航错误:', ev.detail.error); } }); </script> <slot /> </body> </html>
最佳实践:
- 在布局组件中添加
<ViewTransitions /> - 为关键元素使用
transition:name实现共享元素过渡 - 使用
data-astro-transition-prefetch预加载重要链接 - 监听导航事件以处理客户端状态
- 为不同的页面类型使用不同的过渡效果
- 考虑用户体验,不要过度使用动画效果
- 在移动设备上简化过渡效果
兼容性:
视图转换功能需要浏览器支持 View Transitions API。对于不支持的浏览器,Astro 会自动降级为普通的页面导航。
Astro 的视图转换功能为静态站点提供了类似 SPA 的用户体验,同时保持了静态站点的性能和 SEO 优势。