关于 barba-js
barba-js 是一项介绍 Barba.js 页面过渡的技能,面向构建多页网站的开发者。内容涵盖生命周期钩子、页面专属逻辑、路由和动画模式,让网站实现类似 SPA 的导航体验。
主要功能
- 01通过 AJAX 导航且无需整页刷新
- 02用于控制过渡的生命周期钩子
- 03基于命名空间的页面专属逻辑
- 04条件式与路由式过渡
- 05GSAP 动画模式
- 06项目设置工具与起始模板
适用场景
- 01为多页网站添加动画过渡
- 02在导航后运行页面专属初始化
- 03根据导航起点或终点选择过渡
- 04生成 Barba.js 设置与过渡样板代码
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ freshtechbro/ claudedesignskills --skill barba-js安装后在 Claude Code 中输入/barba-js确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
assets/README.mdreferences/api_reference.mdgsap_integration.mdhooks_guide.mdtransition_patterns.mdscripts/project_setup.pytransition_generator.py详细介绍
Barba.js
用于在网站页面之间创建流畅过渡的现代页面过渡库。Barba.js 通过接管导航并在不完整重新加载页面的情况下管理过渡,让多页面网站拥有类似单页应用(SPA)的体验。
概览
Barba.js 是一个轻量级(压缩后仅 7kb)的 JavaScript 库,可拦截页面间的导航,通过 AJAX 获取新内容,并在旧容器与新容器之间实现平滑过渡。它能减少页面加载延迟和 HTTP 请求,同时保留传统多页面架构的优势。
核心功能:
- 无需完整重新加载页面即可实现平滑过渡
- 提供生命周期钩子,精确控制过渡阶段
- 基于视图的逻辑,用于处理页面专属行为
- 内置路由功能,由 @barba/router 插件提供
- 可扩展的插件系统
- 体积小巧,性能出色
- 与框架无关(可与原生 JS、GSAP、anime.js 等配合使用)
核心概念
1. Wrapper、Container 和 Namespace
Barba.js 使用特定的 DOM 结构来管理过渡:
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. 过渡生命周期
Barba.js 为每次导航遵循精确的生命周期:
默认异步流程:
- 用户点击链接
- Barba 拦截导航
- 预获取下一页面(通过 AJAX)
- 缓存新内容
- Leave 钩子——将当前页面动画移出
- 等待移出动画完成
- 移除旧容器,插入新容器
- Enter 钩子——将新页面动画移入
- 等待移入动画完成
- 更新浏览器历史记录
同步流程(使用 sync: true):
- 用户点击链接
- Barba 拦截导航
- 预获取下一页面
- 等待新页面加载
- Leave 和 Enter 钩子同时运行(交叉淡化效果)
- 交换容器
- 更新浏览器历史记录
3. 钩子
Barba 提供 11 个生命周期钩子,用于控制过渡:
钩子执行顺序:
Initial page load:
beforeOnce → once → afterOnce
Every navigation:
before → beforeLeave → leave → afterLeave →
beforeEnter → enter → afterEnter → after
钩子类型:
- 全局钩子:在每次过渡时运行(
barba.hooks.before()) - 过渡钩子:在特定的过渡对象中定义
- 视图钩子:在视图对象中定义,用于处理页面专属逻辑
常见钩子用途:
beforeLeave- 重置滚动位置,准备动画leave- 将当前页面动画移出afterLeave- 清理旧页面beforeEnter- 准备新页面(隐藏元素、设置初始状态)enter- 将新页面动画移入afterEnter- 初始化页面脚本、跟踪分析数据
4. 视图
视图是页面专属逻辑容器,会根据 Namespace 运行:
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();
}
}]
});
常见模式
1. 基本设置
安装:
npm install --save-dev @barba/core
# or
yarn add @barba/core --dev
最简配置:
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
});
}
}]
});
2. 淡入淡出过渡(异步)
经典的淡出、淡入过渡:
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'
});
}
}]
});
3. 交叉淡化过渡(同步)
页面间同时进行淡化:
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'
});
}
}]
});
4. 带重叠效果的滑动过渡
将旧页面滑出,同时将新页面滑入:
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'
});
}
}]
});
5. 过渡规则(条件过渡)
根据导航上下文定义不同的过渡:
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
});
}
}
]
});
6. 用于基于路由的过渡的 Router 插件
使用 @barba/router 实现特定路由的过渡:
安装:
npm install --save-dev @barba/router
用法:
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
});
}
}]
});
7. 加载指示器
在获取页面期间显示加载状态:
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
});
}
}]
});
集成模式
GSAP 集成
Barba.js 可与 GSAP 无缝配合,实现动画效果:
基于时间线的过渡:
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();
}
}]
});
参考 gsap-scrolltrigger 技能,了解高级 GSAP 集成模式。
按视图初始化
按页面初始化库或脚本:
barba.init({
views: [
{
namespace: 'home',
afterEnter() {
// Initialize home page features
initHomepageSlider();
initParallaxEffects();
},
beforeLeave() {
// Clean up
destroyHomepageSlider();
}
},
{
namespace: 'gallery',
afterEnter() {
initLightbox();
initMasonry();
},
beforeLeave() {
destroyLightbox();
}
}
]
});
分析跟踪
在导航时跟踪页面浏览量:
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
});
});
第三方脚本重新初始化
在页面过渡后重新运行脚本:
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();
}
});
性能优化
1. 预获取
使用 @barba/prefetch 在悬停时加载页面:
npm install --save-dev @barba/prefetch
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
}
});
2. 防止布局偏移
设置容器的最小高度,防止内容跳动:
[data-barba="container"] {
min-height: 100vh;
/* Or use viewport height minus header/footer */
min-height: calc(100vh - 80px - 60px);
}
3. 优化动画
使用 GPU 加速属性:
// ✅ 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'
});
4. 清理事件监听器
在 beforeLeave 或视图钩子中移除监听器:
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);
}
}]
});
5. 延迟加载图像
将图像加载推迟到过渡完成后:
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');
});
}
}]
});
常见问题
1. 忘记返回 Promise
问题:过渡会立即完成,而不会等待动画结束。
解决方案:始终返回 Promise,或使用 async/await:
// ❌ 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 });
}
2. 未阻止链接的默认行为
问题:某些链接会导致整个页面重新加载。
解决方案:Barba 会自动阻止内部链接的默认行为,但你可能需要排除外部链接:
barba.init({
prevent: ({ href }) => {
// Allow external links
if (href.indexOf('http') > -1 && href.indexOf(window.location.host) === -1) {
return true;
}
return false;
}
});
3. 页面间的 CSS 冲突
问题:旧页面的 CSS 会在过渡期间影响新页面的布局。
解决方案:使用特定命名空间的 CSS,或重置样式:
/* Namespace-specific styles */
[data-barba-namespace="home"] .hero {
background: blue;
}
[data-barba-namespace="about"] .hero {
background: red;
}
或者在 beforeEnter 中重置:
beforeEnter({ next }) {
// Reset scroll position
window.scrollTo(0, 0);
// Reset any global state
document.body.classList.remove('menu-open');
}
4. 未更新文档标题和 Meta 标签
问题:导航时页面标题和 Meta 标签不会更新。
解决方案:使用 @barba/head 插件或手动更新:
npm install --save-dev @barba/head
import barba from '@barba/core';
import barbaHead from '@barba/head';
barba.use(barbaHead);
barba.init({
// Head plugin automatically updates <head> tags
});
或者手动更新:
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'));
}
}
});
});
5. 页面进入时动画闪烁
问题:新页面会在进入动画开始前闪现。
解决方案:在 CSS 或 beforeEnter 中设置初始不可见状态:
/* CSS approach */
[data-barba="container"] {
opacity: 0;
}
[data-barba="container"].is-visible {
opacity: 1;
}
// JavaScript approach
beforeEnter({ next }) {
gsap.set(next.container, { opacity: 0 });
}
6. 同步过渡时未正确设置位置
问题:容器堆叠会导致同步过渡时发生布局偏移。
解决方案:在过渡期间将容器设为绝对定位:
[data-barba="wrapper"] {
position: relative;
}
[data-barba="container"] {
position: absolute;
top: 0;
left: 0;
width: 100%;
}
或者通过 JavaScript 管理:
barba.init({
transitions: [{
sync: true,
beforeLeave({ current }) {
gsap.set(current.container, {
position: 'absolute',
top: 0,
left: 0,
width: '100%'
});
}
}]
});
资源
此技能包括:
scripts/
用于执行常见 Barba.js 任务的实用工具:
transition_generator.py- 生成过渡样板代码project_setup.py- 初始化 Barba.js 项目结构
references/
详细文档:
api_reference.md- 完整的 Barba.js API(钩子、过渡、视图、路由器)hooks_guide.md- 全部 11 个钩子的执行顺序和使用场景gsap_integration.md- Barba 过渡的 GSAP 动画模式transition_patterns.md- 常见的过渡实现方式
assets/
模板和入门项目:
starter_barba/- 完整的 Barba.js + GSAP 入门模板examples/- 实际过渡实现示例
相关技能
- gsap-scrolltrigger - 用于过渡中的高级 GSAP 动画
- locomotive-scroll - 可与 Barba 结合,实现页面间的平滑滚动
- motion-framer - React 页面过渡的替代方案