vue 实现滚动联动
滚动联动的实现方法
滚动联动通常指多个滚动容器(如多个div或页面区域)在滚动时保持同步。以下是基于Vue的实现方案:
基于事件监听的同步滚动
通过监听scroll事件并动态设置其他容器的滚动位置实现联动:
<template>
<div class="container">
<div ref="leftPanel" class="scroll-panel" @scroll="handleLeftScroll">
<!-- 左侧内容 -->
</div>
<div ref="rightPanel" class="scroll-panel" @scroll="handleRightScroll">
<!-- 右侧内容 -->
</div>
</div>
</template>
<script>
export default {
data() {
return {
isScrolling: false
}
},
methods: {
handleLeftScroll() {
if (this.isScrolling) return
this.isScrolling = true
const leftScrollTop = this.$refs.leftPanel.scrollTop
this.$refs.rightPanel.scrollTop = leftScrollTop
requestAnimationFrame(() => {
this.isScrolling = false
})
},
handleRightScroll() {
if (this.isScrolling) return
this.isScrolling = true
const rightScrollTop = this.$refs.rightPanel.scrollTop
this.$refs.leftPanel.scrollTop = rightScrollTop
requestAnimationFrame(() => {
this.isScrolling = false
})
}
}
}
</script>
使用自定义指令封装
将滚动逻辑封装为可复用的自定义指令:
Vue.directive('scroll-sync', {
inserted(el, binding, vnode) {
const targetEl = document.querySelector(binding.value)
let sourceScrolling = false
let targetScrolling = false
el.addEventListener('scroll', () => {
if (targetScrolling) return
sourceScrolling = true
targetEl.scrollTop = el.scrollTop
requestAnimationFrame(() => {
sourceScrolling = false
})
})
targetEl.addEventListener('scroll', () => {
if (sourceScrolling) return
targetScrolling = true
el.scrollTop = targetEl.scrollTop
requestAnimationFrame(() => {
targetScrolling = false
})
})
}
})
使用方式:
<div v-scroll-sync="'#rightPanel'"></div>
<div id="rightPanel"></div>
性能优化建议
对于大量内容或高频滚动的场景,可采用节流技术减少计算负担:
import { throttle } from 'lodash'
methods: {
handleScroll: throttle(function(scrollTop) {
this.$refs.otherPanel.scrollTop = scrollTop
}, 16) // 60fps的节流间隔
}
跨组件通信方案
当需要联动的组件位于不同层级时,可通过Vuex或事件总线实现:

// 使用事件总线
const bus = new Vue()
// 组件A
this.$refs.scrollContainer.addEventListener('scroll', () => {
bus.$emit('scroll', this.$refs.scrollContainer.scrollTop)
})
// 组件B
bus.$on('scroll', (scrollTop) => {
this.$refs.scrollContainer.scrollTop = scrollTop
})
注意事项
- 避免直接操作DOM时产生无限循环,需设置滚动标志位
- 移动端需考虑touch事件的兼容性
- 对于复杂布局,需计算不同容器的高度比例进行动态调整
- 使用
requestAnimationFrame确保滚动平滑性






