🚀「v-slide-in」+ 瀑布流实战指南:Vue 高级滑入动画一键实现,页面质感瞬间拉满!
🎯 如果你正在开发图片墙、商品展示页或内容分发类页面,想给你的 Vue 项目加点"动感",这篇文章将是你的秘籍!
效果展示

✨ 一、背景介绍
在内容驱动型页面中,比如 图文瀑布流、相册、社交流 等,用户体验离不开一个字:"动"。
静态加载固然稳定,但视觉沉闷。而「滑入 + 懒加载」这种 高效 + 丝滑 的动效体验,正是高级网页的标配。
本文将带你实现一个 Vue 自定义指令 v-slide-in
,让元素 在进入视口时平滑滑入,并与瀑布流布局组件完美结合,呈现类似小红书、B站、Pinterest 的流畅体验!
🧱 二、最终效果
- ✅ 图片从下方淡入滑入
- ✅ 只有当元素出现在用户视口时才会触发动画
- ✅ 配合
waterfall
实现响应式布局和懒加载 - ✅ 性能优秀,无多余重渲染
🛠️ 三、自定义指令 v-slide-in
完整代码
ts
const OFFSET = 100;
const DURATION = 500;
const map = new WeakMap();
const ob = new IntersectionObserver((entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
const animation = map.get(entry.target);
if (animation) {
animation.play();
ob.unobserve(entry.target);
}
}
}
});
export default {
mounted(el: HTMLElement) {
const img = el.querySelector('img');
if (img) {
img.addEventListener('load', () => {
const animation = el.animate(
[
{ transform: `translateY(${OFFSET}px)`, opacity: 0 },
{ transform: `translateY(0px)`, opacity: 1 },
],
{
duration: DURATION,
easing: 'ease-in-out',
fill: 'forwards',
}
);
animation.pause();
ob.observe(el);
map.set(el, animation);
});
}
},
unmounted(el: any) {
ob.unobserve(el);
},
};
🧩 四、逐点剖析:原理 + 实战 🎬 1. IntersectionObserver 是什么? 这是浏览器原生 API,用于检测元素是否进入了用户视口。相比 scroll 事件更加高效、省资源。
ts
const ob = new IntersectionObserver((entries) => {
// 检测是否进入视口
});
🧠 2. WeakMap 用于存储动画对象
ts
Copy
Edit
const map = new WeakMap();
map.set(el, animation);
防止重复创建动画对象,同时自动释放内存,不怕内存泄漏。
🎞️ 3. 使用原生 Web Animations API 创建动画
ts
el.animate([
{ transform: 'translateY(100px)', opacity: 0 },
{ transform: 'translateY(0)', opacity: 1 }
], {
duration: 500,
easing: 'ease-in-out',
fill: 'forwards'
});
🧹 4. 生命周期清理
ts
unmounted(el) {
ob.unobserve(el);
}
避免组件销毁后仍监听,防止资源浪费。
🌊 五、与瀑布流 waterfall
组件配合使用
🔍 场景
- 用户打开页面时加载大量图片或内容卡片
- 内容是动态获取的,图片异步加载
- 需要布局灵活、列数响应式,且页面不卡顿
✅ 效果图示
每张图片进入视口前都是透明 + 下移,进入视口时平滑滑入并淡入,视觉层级瞬间提升。
💡 使用 vue-waterfall-plugin-next 示例
ts
<template>
<Waterfall :list="imageList" :column="4" :gap="16">
<template #default="{ item }">
<div v-slide-in class="card">
<img :src="item.url" alt="图" />
</div>
</template>
</Waterfall>
</template>
<script setup>
import { ref } from 'vue'
import { Waterfall } from 'vue-waterfall-plugin-next'
import 'vue-waterfall-plugin-next/dist/style.css'
const imageList = ref([
{ url: 'https://example.com/1.jpg' },
{ url: 'https://example.com/2.jpg' },
// ...更多图片
])
</script>
<style scoped>
.card {
background: #fff;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
transition: transform 0.2s ease;
}
.card:hover {
transform: translateY(-4px);
}
</style>
🧰 六、优化建议 & 进阶玩法
功能 | 实现方式 |
---|---|
支持动画方向配置 | 通过指令传参如 v-slide-in:bottom |
动画复用优化 | 使用类名 + CSS 动画统一风格 |
多次触发动画 | 移除 unobserve ,或配置触发次数 |
封装成组合函数 | 封装成 useSlideIn() 组合式 API |
📚 七、推荐使用场景
- 👕 电商商品推荐页
- 🖼️ 图库瀑布流
- 📚 内容流平台(如小红书)
- 🧵 社区/视频展示流
- 📱 移动端首页/活动页动效展示
🎯 八、总结
v-slide-in
+waterfall
是一套「轻量级 + 高视觉」的动画组合拳:
- 🎬 动画播放仅在需要时触发
- 🧠 使用原生 API 性能优秀
- 💎 页面丝滑,交互体验更自然
- 🧱 代码结构清晰,方便维护
🙌 如果觉得有帮助欢迎三连支持!
👍 点赞 | ⭐ 收藏 | 📝 留言
我会继续分享更多 Vue 动效、组合 API 封装、性能优化实战内容~欢迎一起交流!