vue实现滑动吸附
Vue 实现滑动吸附效果
滑动吸附效果常见于移动端或需要分步展示内容的场景,以下是几种实现方式:
基于 CSS Scroll Snap
现代浏览器支持的原生 CSS 方案,无需 JavaScript:
<template>
<div class="snap-container">
<div class="snap-item">Section 1</div>
<div class="snap-item">Section 2</div>
<div class="snap-item">Section 3</div>
</div>
</template>
<style>
.snap-container {
scroll-snap-type: y mandatory;
overflow-y: scroll;
height: 100vh;
}
.snap-item {
scroll-snap-align: start;
height: 100vh;
}
</style>
基于 IntersectionObserver API
动态检测元素位置实现精准控制:
export default {
mounted() {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// 当前激活项处理逻辑
console.log(entry.target.id + ' is active');
}
});
}, {
threshold: 0.5,
rootMargin: '0px'
});
document.querySelectorAll('.snap-item').forEach(el => {
observer.observe(el);
});
}
}
结合第三方库(如 vue-use)
使用现成的 Vue 组合式 API:
import { useScroll } from '@vueuse/core'
export default {
setup() {
const { arrivedState, directions } = useScroll(document)
watch(arrivedState, (val) => {
if (val.bottom) {
// 到达底部时执行吸附
document.scrollTo({
top: document.body.scrollHeight,
behavior: 'smooth'
})
}
})
}
}
自定义滚动逻辑
手动实现滚动位置判断:
methods: {
handleScroll() {
const container = this.$el;
const children = container.children;
const scrollTop = container.scrollTop;
const containerHeight = container.clientHeight;
Array.from(children).forEach((child, index) => {
const childTop = child.offsetTop;
const childHeight = child.clientHeight;
if (scrollTop >= childTop - containerHeight/2 &&
scrollTop < childTop + childHeight - containerHeight/2) {
// 当前激活项处理
this.activeIndex = index;
}
});
}
}
注意事项
- 移动端需添加
-webkit-overflow-scrolling: touch增强滚动体验 - 考虑添加防抖处理避免频繁触发滚动事件
- 对于复杂场景可结合 CSS transform 实现平滑过渡
- 浏览器兼容性需测试,特别是 Safari 对 scroll-snap 的支持情况
以上方案可根据具体需求选择,CSS 原生方案性能最佳,JavaScript 方案控制更灵活。







