barba-js
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBarba.js
Barba.js
Modern page transition library for creating fluid, smooth transitions between website pages. Barba.js makes multi-page websites feel like Single Page Applications (SPAs) by hijacking navigation and managing transitions without full page reloads.
一款用于在网站页面之间创建流畅顺滑过渡效果的现代页面过渡库。Barba.js通过拦截导航并在无需整页刷新的情况下管理过渡效果,让多页面网站拥有类单页应用(SPA)的体验。
Overview
概述
Barba.js is a lightweight (7kb minified and compressed) JavaScript library that intercepts navigation between pages, fetches new content via AJAX, and smoothly transitions between old and new containers. It reduces page load delays and HTTP requests while maintaining the benefits of traditional multi-page architecture.
Core Features:
- Smooth page transitions without full reloads
- Lifecycle hooks for precise control over transition phases
- View-based logic for page-specific behaviors
- Built-in routing with @barba/router plugin
- Extensible plugin system
- Small footprint and high performance
- Framework-agnostic (works with vanilla JS, GSAP, anime.js, etc.)
Barba.js是一款轻量级(压缩后仅7kb)的JavaScript库,它拦截页面间的导航请求,通过AJAX获取新内容,并在旧容器和新容器之间实现顺滑过渡。它减少了页面加载延迟和HTTP请求,同时保留了传统多页面架构的优势。
核心特性:
- 无需整页刷新的顺滑页面过渡
- 生命周期钩子,可精确控制过渡阶段
- 基于视图的逻辑,支持页面特定行为
- 内置路由(搭配@barba/router插件)
- 可扩展的插件系统
- 体积小巧且性能优异
- 与框架无关(可配合原生JS、GSAP、anime.js等使用)
Core Concepts
核心概念
1. Wrapper, Container, and Namespace
1. Wrapper、Container与Namespace
Barba.js uses a specific DOM structure to manage transitions:
HTML Structure:
html
<body data-barba="wrapper">
<!-- Static elements (header, nav) stay outside container -->
<header>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
</header>
<!-- Dynamic content goes in container -->
<main data-barba="container" data-barba-namespace="home">
<!-- This content changes on navigation -->
<h1>Home Page</h1>
<p>Content that will transition out...</p>
</main>
<!-- Static footer outside container -->
<footer>© 2025</footer>
</body>Three Key Elements:
-
Wrapper ()
data-barba="wrapper"- Outermost container
- Everything inside wrapper but outside container stays persistent
- Ideal for headers, navigation, footers that don't change
-
Container ()
data-barba="container"- Dynamic content area that updates on navigation
- Only this section gets replaced during transitions
- Must exist on every page
-
Namespace ()
data-barba-namespace="home"- Unique identifier for each page type
- Used in transition rules and view logic
- Examples: "home", "about", "product", "blog-post"
Barba.js使用特定的DOM结构来管理过渡效果:
HTML结构:
html
<body data-barba="wrapper">
<!-- 静态元素(页眉、导航)放在容器外部 -->
<header>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
</header>
<!-- 动态内容放在容器内部 -->
<main data-barba="container" data-barba-namespace="home">
<!-- 导航时该内容会变化 -->
<h1>Home Page</h1>
<p>Content that will transition out...</p>
</main>
<!-- 静态页脚放在容器外部 -->
<footer>© 2025</footer>
</body>三个关键元素:
-
Wrapper ()
data-barba="wrapper"- 最外层容器
- Wrapper内部但Container外部的所有元素会保持持久化
- 适合放置页眉、导航、页脚等无需变化的元素
-
Container ()
data-barba="container"- 导航时会更新的动态内容区域
- 过渡期间只有该部分会被替换
- 每个页面都必须包含该元素
-
Namespace ()
data-barba-namespace="home"- 每种页面类型的唯一标识符
- 用于过渡规则和视图逻辑
- 示例:"home"、"about"、"product"、"blog-post"
2. Transition Lifecycle
2. 过渡生命周期
Barba.js follows a precise lifecycle for each navigation:
Default Async Flow:
- User clicks link
- Barba intercepts navigation
- Prefetch next page (via AJAX)
- Cache new content
- Leave hook - Animate current page out
- Wait for leave animation to complete
- Remove old container, insert new container
- Enter hook - Animate new page in
- Wait for enter animation to complete
- Update browser history
Sync Flow (with ):
sync: true- User clicks link
- Barba intercepts navigation
- Prefetch next page
- Wait for new page to load
- Leave and Enter hooks run simultaneously (crossfade effect)
- Swap containers
- Update browser history
Barba.js为每次导航遵循精确的生命周期:
默认异步流程:
- 用户点击链接
- Barba拦截导航请求
- 预加载下一页内容(通过AJAX)
- 缓存新内容
- Leave钩子 - 为当前页面添加退出动画
- 等待退出动画完成
- 移除旧容器,插入新容器
- Enter钩子 - 为新页面添加进入动画
- 等待进入动画完成
- 更新浏览器历史记录
同步流程(启用):
sync: true- 用户点击链接
- Barba拦截导航请求
- 预加载下一页内容
- 等待新页面加载完成
- Leave与Enter钩子同时执行(交叉淡入淡出效果)
- 切换容器
- 更新浏览器历史记录
3. Hooks
3. 钩子
Barba provides 11 lifecycle hooks for controlling transitions:
Hook Execution Order:
Initial page load:
beforeOnce → once → afterOnce
Every navigation:
before → beforeLeave → leave → afterLeave →
beforeEnter → enter → afterEnter → afterHook Types:
- Global hooks: Run on every transition ()
barba.hooks.before() - Transition hooks: Defined within specific transition objects
- View hooks: Defined within view objects for page-specific logic
Common Hook Use Cases:
- - Reset scroll position, prepare animations
beforeLeave - - Animate current page out
leave - - Clean up old page
afterLeave - - Prepare new page (hide elements, set initial states)
beforeEnter - - Animate new page in
enter - - Initialize page scripts, analytics tracking
afterEnter
Barba提供11个生命周期钩子用于控制过渡效果:
钩子执行顺序:
初始页面加载:
beforeOnce → once → afterOnce
每次导航:
before → beforeLeave → leave → afterLeave →
beforeEnter → enter → afterEnter → after钩子类型:
- 全局钩子: 在每次过渡时都会执行()
barba.hooks.before() - 过渡钩子: 在特定过渡对象中定义
- 视图钩子: 在视图对象中定义,用于页面特定逻辑
常见钩子使用场景:
- - 重置滚动位置、准备动画
beforeLeave - - 为当前页面添加退出动画
leave - - 清理旧页面
afterLeave - - 准备新页面(隐藏元素、设置初始状态)
beforeEnter - - 为新页面添加进入动画
enter - - 初始化页面脚本、分析跟踪
afterEnter
4. Views
4. 视图
Views are page-specific logic containers that run based on namespace:
javascript
barba.init({
views: [{
namespace: 'home',
beforeEnter() {
// Home-specific setup
console.log('Entering home page');
},
afterEnter() {
// Initialize home page features
initHomeSlider();
}
}, {
namespace: 'product',
beforeEnter() {
console.log('Entering product page');
},
afterEnter() {
initProductGallery();
}
}]
});视图是基于Namespace运行的页面特定逻辑容器:
javascript
barba.init({
views: [{
namespace: 'home',
beforeEnter() {
// 首页专属设置
console.log('Entering home page');
},
afterEnter() {
// 初始化首页功能
initHomeSlider();
}
}, {
namespace: 'product',
beforeEnter() {
console.log('Entering product page');
},
afterEnter() {
initProductGallery();
}
}]
});Common Patterns
常见模式
1. Basic Setup
1. 基础设置
Installation:
bash
npm install --save-dev @barba/core安装:
bash
npm install --save-dev @barba/coreor
或
yarn add @barba/core --dev
**Minimal Configuration**:
```javascript
import barba from '@barba/core';
barba.init({
transitions: [{
name: 'default',
leave({ current }) {
// Fade out current page
return gsap.to(current.container, {
opacity: 0,
duration: 0.5
});
},
enter({ next }) {
// Fade in new page
return gsap.from(next.container, {
opacity: 0,
duration: 0.5
});
}
}]
});yarn add @barba/core --dev
**最简配置**:
```javascript
import barba from '@barba/core';
barba.init({
transitions: [{
name: 'default',
leave({ current }) {
// 为当前页面添加淡出动画
return gsap.to(current.container, {
opacity: 0,
duration: 0.5
});
},
enter({ next }) {
// 为新页面添加淡入动画
return gsap.from(next.container, {
opacity: 0,
duration: 0.5
});
}
}]
});2. Fade Transition (Async)
2. 淡入淡出过渡(异步)
Classic fade-out, fade-in transition:
javascript
import barba from '@barba/core';
import gsap from 'gsap';
barba.init({
transitions: [{
name: 'fade',
async leave({ current }) {
await gsap.to(current.container, {
opacity: 0,
duration: 0.5,
ease: 'power2.inOut'
});
},
async enter({ next }) {
// Start invisible
gsap.set(next.container, { opacity: 0 });
// Fade in
await gsap.to(next.container, {
opacity: 1,
duration: 0.5,
ease: 'power2.inOut'
});
}
}]
});经典的先淡出、再淡入的过渡效果:
javascript
import barba from '@barba/core';
import gsap from 'gsap';
barba.init({
transitions: [{
name: 'fade',
async leave({ current }) {
await gsap.to(current.container, {
opacity: 0,
duration: 0.5,
ease: 'power2.inOut'
});
},
async enter({ next }) {
// 初始状态设为不可见
gsap.set(next.container, { opacity: 0 });
// 淡入
await gsap.to(next.container, {
opacity: 1,
duration: 0.5,
ease: 'power2.inOut'
});
}
}]
});3. Crossfade Transition (Sync)
3. 交叉淡入淡出过渡(同步)
Simultaneous fade between pages:
javascript
barba.init({
transitions: [{
name: 'crossfade',
sync: true, // Enable sync mode
leave({ current }) {
return gsap.to(current.container, {
opacity: 0,
duration: 0.8,
ease: 'power2.inOut'
});
},
enter({ next }) {
return gsap.from(next.container, {
opacity: 0,
duration: 0.8,
ease: 'power2.inOut'
});
}
}]
});页面之间同时进行淡入淡出的效果:
javascript
barba.init({
transitions: [{
name: 'crossfade',
sync: true, // 启用同步模式
leave({ current }) {
return gsap.to(current.container, {
opacity: 0,
duration: 0.8,
ease: 'power2.inOut'
});
},
enter({ next }) {
return gsap.from(next.container, {
opacity: 0,
duration: 0.8,
ease: 'power2.inOut'
});
}
}]
});4. Slide Transition with Overlap
4. 带重叠效果的滑动过渡
Slide old page out, new page in with overlap:
javascript
barba.init({
transitions: [{
name: 'slide',
sync: true,
leave({ current }) {
return gsap.to(current.container, {
x: '-100%',
duration: 0.7,
ease: 'power3.inOut'
});
},
enter({ next }) {
// Start off-screen right
gsap.set(next.container, { x: '100%' });
// Slide in from right
return gsap.to(next.container, {
x: '0%',
duration: 0.7,
ease: 'power3.inOut'
});
}
}]
});旧页面滑出、新页面滑入并带有重叠效果:
javascript
barba.init({
transitions: [{
name: 'slide',
sync: true,
leave({ current }) {
return gsap.to(current.container, {
x: '-100%',
duration: 0.7,
ease: 'power3.inOut'
});
},
enter({ next }) {
// 初始状态设为屏幕右侧外
gsap.set(next.container, { x: '100%' });
// 从右侧滑入
return gsap.to(next.container, {
x: '0%',
duration: 0.7,
ease: 'power3.inOut'
});
}
}]
});5. Transition Rules (Conditional Transitions)
5. 过渡规则(条件过渡)
Define different transitions based on navigation context:
javascript
barba.init({
transitions: [
// Home to any page: fade
{
name: 'from-home-fade',
from: { namespace: 'home' },
leave({ current }) {
return gsap.to(current.container, {
opacity: 0,
duration: 0.5
});
},
enter({ next }) {
return gsap.from(next.container, {
opacity: 0,
duration: 0.5
});
}
},
// Product to product: slide left
{
name: 'product-to-product',
from: { namespace: 'product' },
to: { namespace: 'product' },
leave({ current }) {
return gsap.to(current.container, {
x: '-100%',
duration: 0.6
});
},
enter({ next }) {
gsap.set(next.container, { x: '100%' });
return gsap.to(next.container, {
x: '0%',
duration: 0.6
});
}
},
// Default fallback
{
name: 'default',
leave({ current }) {
return gsap.to(current.container, {
opacity: 0,
duration: 0.3
});
},
enter({ next }) {
return gsap.from(next.container, {
opacity: 0,
duration: 0.3
});
}
}
]
});根据导航上下文定义不同的过渡效果:
javascript
barba.init({
transitions: [
// 从首页到任意页面:淡入淡出
{
name: 'from-home-fade',
from: { namespace: 'home' },
leave({ current }) {
return gsap.to(current.container, {
opacity: 0,
duration: 0.5
});
},
enter({ next }) {
return gsap.from(next.container, {
opacity: 0,
duration: 0.5
});
}
},
// 从产品页到产品页:向左滑动
{
name: 'product-to-product',
from: { namespace: 'product' },
to: { namespace: 'product' },
leave({ current }) {
return gsap.to(current.container, {
x: '-100%',
duration: 0.6
});
},
enter({ next }) {
gsap.set(next.container, { x: '100%' });
return gsap.to(next.container, {
x: '0%',
duration: 0.6
});
}
},
// 默认回退过渡
{
name: 'default',
leave({ current }) {
return gsap.to(current.container, {
opacity: 0,
duration: 0.3
});
},
enter({ next }) {
return gsap.from(next.container, {
opacity: 0,
duration: 0.3
});
}
}
]
});6. Router Plugin for Route-Based Transitions
6. 路由插件(基于路由的过渡)
Use for route-specific transitions:
@barba/routerInstallation:
bash
npm install --save-dev @barba/routerUsage:
javascript
import barba from '@barba/core';
import barbaPrefetch from '@barba/prefetch';
import barbaRouter from '@barba/router';
// Define routes
barbaRouter.init({
routes: [
{ path: '/', name: 'home' },
{ path: '/about', name: 'about' },
{ path: '/products/:id', name: 'product' }, // Dynamic segment
{ path: '/blog/:category/:slug', name: 'blog-post' }
]
});
barba.use(barbaRouter);
barba.use(barbaPrefetch); // Optional: prefetch on hover
barba.init({
transitions: [{
name: 'product-transition',
to: { route: 'product' }, // Trigger on route name
leave({ current }) {
return gsap.to(current.container, {
scale: 0.95,
opacity: 0,
duration: 0.5
});
},
enter({ next }) {
return gsap.from(next.container, {
scale: 1.05,
opacity: 0,
duration: 0.5
});
}
}]
});使用实现基于路由的过渡效果:
@barba/router安装:
bash
npm install --save-dev @barba/router使用:
javascript
import barba from '@barba/core';
import barbaPrefetch from '@barba/prefetch';
import barbaRouter from '@barba/router';
// 定义路由
barbaRouter.init({
routes: [
{ path: '/', name: 'home' },
{ path: '/about', name: 'about' },
{ path: '/products/:id', name: 'product' }, // 动态分段
{ path: '/blog/:category/:slug', name: 'blog-post' }
]
});
barba.use(barbaRouter);
barba.use(barbaPrefetch); // 可选:悬停时预加载
barba.init({
transitions: [{
name: 'product-transition',
to: { route: 'product' }, // 根据路由名称触发
leave({ current }) {
return gsap.to(current.container, {
scale: 0.95,
opacity: 0,
duration: 0.5
});
},
enter({ next }) {
return gsap.from(next.container, {
scale: 1.05,
opacity: 0,
duration: 0.5
});
}
}]
});7. Loading Indicator
7. 加载指示器
Show loading state during page fetch:
javascript
barba.init({
transitions: [{
async leave({ current }) {
// Show loader
const loader = document.querySelector('.loader');
gsap.set(loader, { display: 'flex', opacity: 0 });
gsap.to(loader, { opacity: 1, duration: 0.3 });
// Fade out page
await gsap.to(current.container, {
opacity: 0,
duration: 0.5
});
},
async enter({ next }) {
// Hide loader
const loader = document.querySelector('.loader');
await gsap.to(loader, { opacity: 0, duration: 0.3 });
gsap.set(loader, { display: 'none' });
// Fade in page
await gsap.from(next.container, {
opacity: 0,
duration: 0.5
});
}
}]
});在页面获取过程中显示加载状态:
javascript
barba.init({
transitions: [{
async leave({ current }) {
// 显示加载器
const loader = document.querySelector('.loader');
gsap.set(loader, { display: 'flex', opacity: 0 });
gsap.to(loader, { opacity: 1, duration: 0.3 });
// 页面淡出
await gsap.to(current.container, {
opacity: 0,
duration: 0.5
});
},
async enter({ next }) {
// 隐藏加载器
const loader = document.querySelector('.loader');
await gsap.to(loader, { opacity: 0, duration: 0.3 });
gsap.set(loader, { display: 'none' });
// 页面淡入
await gsap.from(next.container, {
opacity: 0,
duration: 0.5
});
}
}]
});Integration Patterns
集成模式
GSAP Integration
GSAP集成
Barba.js works seamlessly with GSAP for animations:
Timeline-Based Transitions:
javascript
import barba from '@barba/core';
import gsap from 'gsap';
barba.init({
transitions: [{
async leave({ current }) {
const tl = gsap.timeline();
tl.to(current.container.querySelector('h1'), {
y: -50,
opacity: 0,
duration: 0.3
})
.to(current.container.querySelector('.content'), {
y: -30,
opacity: 0,
duration: 0.3
}, '-=0.2')
.to(current.container, {
opacity: 0,
duration: 0.2
});
await tl.play();
},
async enter({ next }) {
const tl = gsap.timeline();
// Set initial states
gsap.set(next.container, { opacity: 0 });
gsap.set(next.container.querySelector('h1'), { y: 50, opacity: 0 });
gsap.set(next.container.querySelector('.content'), { y: 30, opacity: 0 });
tl.to(next.container, {
opacity: 1,
duration: 0.2
})
.to(next.container.querySelector('h1'), {
y: 0,
opacity: 1,
duration: 0.5,
ease: 'power3.out'
})
.to(next.container.querySelector('.content'), {
y: 0,
opacity: 1,
duration: 0.5,
ease: 'power3.out'
}, '-=0.3');
await tl.play();
}
}]
});Reference gsap-scrolltrigger skill for advanced GSAP integration patterns.
Barba.js可与GSAP无缝配合实现动画效果:
基于时间轴的过渡:
javascript
import barba from '@barba/core';
import gsap from 'gsap';
barba.init({
transitions: [{
async leave({ current }) {
const tl = gsap.timeline();
tl.to(current.container.querySelector('h1'), {
y: -50,
opacity: 0,
duration: 0.3
})
.to(current.container.querySelector('.content'), {
y: -30,
opacity: 0,
duration: 0.3
}, '-=0.2')
.to(current.container, {
opacity: 0,
duration: 0.2
});
await tl.play();
},
async enter({ next }) {
const tl = gsap.timeline();
// 设置初始状态
gsap.set(next.container, { opacity: 0 });
gsap.set(next.container.querySelector('h1'), { y: 50, opacity: 0 });
gsap.set(next.container.querySelector('.content'), { y: 30, opacity: 0 });
tl.to(next.container, {
opacity: 1,
duration: 0.2
})
.to(next.container.querySelector('h1'), {
y: 0,
opacity: 1,
duration: 0.5,
ease: 'power3.out'
})
.to(next.container.querySelector('.content'), {
y: 0,
opacity: 1,
duration: 0.5,
ease: 'power3.out'
}, '-=0.3');
await tl.play();
}
}]
});参考gsap-scrolltrigger技能获取更高级的GSAP集成模式。
View-Specific Initialization
基于视图的初始化
Initialize libraries or scripts per page:
javascript
barba.init({
views: [
{
namespace: 'home',
afterEnter() {
// Initialize home page features
initHomepageSlider();
initParallaxEffects();
},
beforeLeave() {
// Clean up
destroyHomepageSlider();
}
},
{
namespace: 'gallery',
afterEnter() {
initLightbox();
initMasonry();
},
beforeLeave() {
destroyLightbox();
}
}
]
});按页面初始化库或脚本:
javascript
barba.init({
views: [
{
namespace: 'home',
afterEnter() {
// 初始化首页功能
initHomepageSlider();
initParallaxEffects();
},
beforeLeave() {
// 清理
destroyHomepageSlider();
}
},
{
namespace: 'gallery',
afterEnter() {
initLightbox();
initMasonry();
},
beforeLeave() {
destroyLightbox();
}
}
]
});Analytics Tracking
分析跟踪
Track page views on navigation:
javascript
barba.hooks.after(() => {
// Google Analytics
if (typeof gtag !== 'undefined') {
gtag('config', 'GA_MEASUREMENT_ID', {
page_path: window.location.pathname
});
}
// Or use data layer
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'pageview',
page: window.location.pathname
});
});在导航时跟踪页面浏览量:
javascript
barba.hooks.after(() => {
// Google Analytics
if (typeof gtag !== 'undefined') {
gtag('config', 'GA_MEASUREMENT_ID', {
page_path: window.location.pathname
});
}
// 或使用数据层
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'pageview',
page: window.location.pathname
});
});Third-Party Script Re-Initialization
第三方脚本重新初始化
Re-run scripts after page transitions:
javascript
barba.hooks.after(() => {
// Re-initialize third-party widgets
if (typeof twttr !== 'undefined') {
twttr.widgets.load(); // Twitter widgets
}
if (typeof FB !== 'undefined') {
FB.XFBML.parse(); // Facebook widgets
}
// Re-run syntax highlighting
if (typeof Prism !== 'undefined') {
Prism.highlightAll();
}
});页面过渡后重新运行脚本:
javascript
barba.hooks.after(() => {
// 重新初始化第三方小部件
if (typeof twttr !== 'undefined') {
twttr.widgets.load(); // Twitter小部件
}
if (typeof FB !== 'undefined') {
FB.XFBML.parse(); // Facebook小部件
}
// 重新运行语法高亮
if (typeof Prism !== 'undefined') {
Prism.highlightAll();
}
});Performance Optimization
性能优化
1. Prefetching
1. 预加载
Use to load pages on hover:
@barba/prefetchbash
npm install --save-dev @barba/prefetchjavascript
import barba from '@barba/core';
import barbaPrefetch from '@barba/prefetch';
barba.use(barbaPrefetch);
barba.init({
// Prefetch fires on link hover by default
prefetch: {
root: null, // Observe all links
timeout: 3000 // Cache timeout in ms
}
});使用在鼠标悬停时加载页面:
@barba/prefetchbash
npm install --save-dev @barba/prefetchjavascript
import barba from '@barba/core';
import barbaPrefetch from '@barba/prefetch';
barba.use(barbaPrefetch);
barba.init({
// 默认在链接悬停时触发预加载
prefetch: {
root: null, // 监听所有链接
timeout: 3000 // 缓存超时时间(毫秒)
}
});2. Prevent Layout Shift
2. 防止布局偏移
Set container min-height to prevent content jump:
css
[data-barba="container"] {
min-height: 100vh;
/* Or use viewport height minus header/footer */
min-height: calc(100vh - 80px - 60px);
}设置容器最小高度以避免内容跳动:
css
[data-barba="container"] {
min-height: 100vh;
// 或使用视口高度减去页眉/页脚高度
min-height: calc(100vh - 80px - 60px);
}3. Optimize Animations
3. 优化动画
Use GPU-accelerated properties:
javascript
// ✅ Good - GPU accelerated
gsap.to(element, {
opacity: 0,
x: -100,
scale: 0.9,
rotation: 45
});
// ❌ Avoid - causes reflow/repaint
gsap.to(element, {
width: '50%',
height: '300px',
top: '100px'
});使用GPU加速属性:
javascript
// ✅ 推荐 - GPU加速
gsap.to(element, {
opacity: 0,
x: -100,
scale: 0.9,
rotation: 45
});
// ❌ 避免 - 会导致重排/重绘
gsap.to(element, {
width: '50%',
height: '300px',
top: '100px'
});4. Clean Up Event Listeners
4. 清理事件监听器
Remove listeners in or view hooks:
beforeLeavejavascript
barba.init({
views: [{
namespace: 'home',
afterEnter() {
// Add listeners
this.clickHandler = () => console.log('clicked');
document.querySelector('.btn').addEventListener('click', this.clickHandler);
},
beforeLeave() {
// Remove listeners
document.querySelector('.btn').removeEventListener('click', this.clickHandler);
}
}]
});在或视图钩子中移除监听器:
beforeLeavejavascript
barba.init({
views: [{
namespace: 'home',
afterEnter() {
// 添加监听器
this.clickHandler = () => console.log('clicked');
document.querySelector('.btn').addEventListener('click', this.clickHandler);
},
beforeLeave() {
// 移除监听器
document.querySelector('.btn').removeEventListener('click', this.clickHandler);
}
}]
});5. Lazy Load Images
5. 图片懒加载
Defer image loading until after transition:
javascript
barba.init({
transitions: [{
async enter({ next }) {
// Complete transition first
await gsap.from(next.container, {
opacity: 0,
duration: 0.5
});
// Then load images
const images = next.container.querySelectorAll('img[data-src]');
images.forEach(img => {
img.src = img.dataset.src;
img.removeAttribute('data-src');
});
}
}]
});延迟加载图片直到过渡完成:
javascript
barba.init({
transitions: [{
async enter({ next }) {
// 先完成过渡
await gsap.from(next.container, {
opacity: 0,
duration: 0.5
});
// 然后加载图片
const images = next.container.querySelectorAll('img[data-src]');
images.forEach(img => {
img.src = img.dataset.src;
img.removeAttribute('data-src');
});
}
}]
});Common Pitfalls
常见陷阱
1. Forgetting to Return Promises
1. 忘记返回Promise
Problem: Transitions complete instantly without waiting for animations.
Solution: Always return promises or use :
async/awaitjavascript
// ❌ Wrong - animation starts but doesn't wait
leave({ current }) {
gsap.to(current.container, { opacity: 0, duration: 0.5 });
}
// ✅ Correct - returns promise
leave({ current }) {
return gsap.to(current.container, { opacity: 0, duration: 0.5 });
}
// ✅ Also correct - async/await
async leave({ current }) {
await gsap.to(current.container, { opacity: 0, duration: 0.5 });
}问题: 过渡会立即完成,不会等待动画结束。
解决方案: 始终返回Promise或使用:
async/awaitjavascript
// ❌ 错误 - 动画启动但不会等待
leave({ current }) {
gsap.to(current.container, { opacity: 0, duration: 0.5 });
}
// ✅ 正确 - 返回Promise
leave({ current }) {
return gsap.to(current.container, { opacity: 0, duration: 0.5 });
}
// ✅ 同样正确 - 使用async/await
async leave({ current }) {
await gsap.to(current.container, { opacity: 0, duration: 0.5 });
}2. Not Preventing Default Link Behavior
2. 未阻止链接默认行为
Problem: Some links cause full page reloads.
Solution: Barba automatically prevents default on internal links, but you may need to exclude external links:
javascript
barba.init({
prevent: ({ href }) => {
// Allow external links
if (href.indexOf('http') > -1 && href.indexOf(window.location.host) === -1) {
return true;
}
return false;
}
});问题: 部分链接会导致整页刷新。
解决方案: Barba会自动阻止内部链接的默认行为,但你可能需要排除外部链接:
javascript
barba.init({
prevent: ({ href }) => {
// 允许外部链接
if (href.indexOf('http') > -1 && href.indexOf(window.location.host) === -1) {
return true;
}
return false;
}
});3. CSS Conflicts Between Pages
3. 页面间CSS冲突
Problem: Old page CSS affects new page layout during transition.
Solution: Use namespace-specific CSS or reset styles:
css
/* Namespace-specific styles */
[data-barba-namespace="home"] .hero {
background: blue;
}
[data-barba-namespace="about"] .hero {
background: red;
}Or reset in :
beforeEnterjavascript
beforeEnter({ next }) {
// Reset scroll position
window.scrollTo(0, 0);
// Reset any global state
document.body.classList.remove('menu-open');
}问题: 旧页面的CSS在过渡期间影响新页面布局。
解决方案: 使用Namespace专属CSS或重置样式:
css
/* Namespace专属样式 */
[data-barba-namespace="home"] .hero {
background: blue;
}
[data-barba-namespace="about"] .hero {
background: red;
}或在中重置:
beforeEnterjavascript
beforeEnter({ next }) {
// 重置滚动位置
window.scrollTo(0, 0);
// 重置全局状态
document.body.classList.remove('menu-open');
}4. Not Updating Document Title and Meta Tags
4. 未更新文档标题和元标签
Problem: Page title and meta tags don't update on navigation.
Solution: Use plugin or update manually:
@barba/headbash
npm install --save-dev @barba/headjavascript
import barba from '@barba/core';
import barbaHead from '@barba/head';
barba.use(barbaHead);
barba.init({
// Head plugin automatically updates <head> tags
});Or manually:
javascript
barba.hooks.after(({ next }) => {
// Update title
document.title = next.html.querySelector('title').textContent;
// Update meta tags
const newMeta = next.html.querySelectorAll('meta');
newMeta.forEach(meta => {
const name = meta.getAttribute('name') || meta.getAttribute('property');
if (name) {
const existing = document.querySelector(`meta[name="${name}"], meta[property="${name}"]`);
if (existing) {
existing.setAttribute('content', meta.getAttribute('content'));
}
}
});
});问题: 导航时页面标题和元标签不会更新。
解决方案: 使用插件或手动更新:
@barba/headbash
npm install --save-dev @barba/headjavascript
import barba from '@barba/core';
import barbaHead from '@barba/head';
barba.use(barbaHead);
barba.init({
// Head插件会自动更新<head>标签
});或手动更新:
javascript
barba.hooks.after(({ next }) => {
// 更新标题
document.title = next.html.querySelector('title').textContent;
// 更新元标签
const newMeta = next.html.querySelectorAll('meta');
newMeta.forEach(meta => {
const name = meta.getAttribute('name') || meta.getAttribute('property');
if (name) {
const existing = document.querySelector(`meta[name="${name}"], meta[property="${name}"]`);
if (existing) {
existing.setAttribute('content', meta.getAttribute('content'));
}
}
});
});5. Animation Flicker on Enter
5. 进入动画闪烁
Problem: New page flashes visible before enter animation starts.
Solution: Set initial invisible state in CSS or :
beforeEntercss
/* CSS approach */
[data-barba="container"] {
opacity: 0;
}
[data-barba="container"].is-visible {
opacity: 1;
}javascript
// JavaScript approach
beforeEnter({ next }) {
gsap.set(next.container, { opacity: 0 });
}问题: 新页面在进入动画开始前会短暂闪烁可见。
解决方案: 在CSS或中设置初始不可见状态:
beforeEntercss
/* CSS方式 */
[data-barba="container"] {
opacity: 0;
}
[data-barba="container"].is-visible {
opacity: 1;
}javascript
// JavaScript方式
beforeEnter({ next }) {
gsap.set(next.container, { opacity: 0 });
}6. Sync Transitions Without Proper Positioning
6. 同步过渡未正确定位
Problem: Sync transitions cause layout shift as containers stack.
Solution: Position containers absolutely during transition:
css
[data-barba="wrapper"] {
position: relative;
}
[data-barba="container"] {
position: absolute;
top: 0;
left: 0;
width: 100%;
}Or manage in JavaScript:
javascript
barba.init({
transitions: [{
sync: true,
beforeLeave({ current }) {
gsap.set(current.container, {
position: 'absolute',
top: 0,
left: 0,
width: '100%'
});
}
}]
});问题: 同步过渡时容器堆叠会导致布局偏移。
解决方案: 过渡期间将容器设为绝对定位:
css
[data-barba="wrapper"] {
position: relative;
}
[data-barba="container"] {
position: absolute;
top: 0;
left: 0;
width: 100%;
}或在JavaScript中管理:
javascript
barba.init({
transitions: [{
sync: true,
beforeLeave({ current }) {
gsap.set(current.container, {
position: 'absolute',
top: '0',
left: '0',
width: '100%'
});
}
}]
});Resources
资源
This skill includes:
本技能包含:
scripts/
scripts/
Executable utilities for common Barba.js tasks:
- - Generate transition boilerplate code
transition_generator.py - - Initialize Barba.js project structure
project_setup.py
用于Barba.js常见任务的可执行工具:
- - 生成过渡模板代码
transition_generator.py - - 初始化Barba.js项目结构
project_setup.py
references/
references/
Detailed documentation:
- - Complete Barba.js API (hooks, transitions, views, router)
api_reference.md - - All 11 hooks with execution order and use cases
hooks_guide.md - - GSAP animation patterns for Barba transitions
gsap_integration.md - - Common transition implementations
transition_patterns.md
详细文档:
- - 完整的Barba.js API(钩子、过渡、视图、路由)
api_reference.md - - 全部11个钩子的执行顺序和使用场景
hooks_guide.md - - 适用于Barba过渡的GSAP动画模式
gsap_integration.md - - 常见过渡实现方案
transition_patterns.md
assets/
assets/
Templates and starter projects:
- - Complete Barba.js + GSAP starter template
starter_barba/ - - Real-world transition implementations
examples/
模板和启动项目:
- - 完整的Barba.js + GSAP启动模板
starter_barba/ - - 真实场景下的过渡实现
examples/
Related Skills
相关技能
- gsap-scrolltrigger - For advanced GSAP animations in transitions
- locomotive-scroll - Can be combined with Barba for smooth scrolling between pages
- motion-framer - Alternative approach for React-based page transitions
- gsap-scrolltrigger - 用于过渡中的高级GSAP动画
- locomotive-scroll - 可与Barba配合实现页面间的顺滑滚动
- motion-framer - React项目页面过渡的替代方案