vue 实现滚动联动
滚动联动实现方法
滚动联动通常指多个滚动容器(如页面区域、侧边栏、表格等)在滚动时保持同步。以下是基于Vue的实现方案:
基础事件监听方案
通过监听滚动事件并手动同步滚动位置:
<template>
<div class="container">
<div class="box1" ref="box1" @scroll="handleScroll(1)">内容区域1...</div>
<div class="box2" ref="box2" @scroll="handleScroll(2)">内容区域2...</div>
</div>
</template>
<script>
export default {
data() {
return {
isScrolling: false
}
},
methods: {
handleScroll(source) {
if (this.isScrolling) return;
this.isScrolling = true;
const targetBox = source === 1 ? this.$refs.box2 : this.$refs.box1;
const sourceBox = source === 1 ? this.$refs.box1 : this.$refs.box2;
targetBox.scrollTop = sourceBox.scrollTop;
targetBox.scrollLeft = sourceBox.scrollLeft;
requestAnimationFrame(() => {
this.isScrolling = false;
});
}
}
}
</script>
使用自定义指令
封装为可复用的自定义指令:
// main.js
Vue.directive('sync-scroll', {
bind(el, binding, vnode) {
const target = document.querySelector(binding.value);
el.__syncScroll__ = (e) => {
if (target && !target.__isScrolling__) {
target.__isScrolling__ = true;
target.scrollTop = el.scrollTop;
target.scrollLeft = el.scrollLeft;
setTimeout(() => {
target.__isScrolling__ = false;
}, 50);
}
};
el.addEventListener('scroll', el.__syncScroll__);
},
unbind(el) {
el.removeEventListener('scroll', el.__syncScroll__);
}
});
// 使用方式
<div v-sync-scroll="'.target-class'"></div>
复杂表格联动方案
对于表格行列联动滚动:
<template>
<div class="table-container">
<div class="header" ref="header" @scroll="syncHorizontalScroll">
<!-- 表头内容 -->
</div>
<div class="body" ref="body" @scroll="syncBodyScroll">
<!-- 表格主体内容 -->
</div>
</div>
</template>
<script>
export default {
methods: {
syncHorizontalScroll() {
this.$refs.body.scrollLeft = this.$refs.header.scrollLeft;
},
syncBodyScroll() {
this.$refs.header.scrollLeft = this.$refs.body.scrollLeft;
}
}
}
</script>
性能优化建议
滚动事件高频触发,需注意性能优化:
// 使用requestAnimationFrame优化
function throttleScroll(callback) {
let ticking = false;
return function() {
if (!ticking) {
window.requestAnimationFrame(() => {
callback();
ticking = false;
});
ticking = true;
}
};
}
// 使用IntersectionObserver实现懒加载联动
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// 处理联动逻辑
}
});
});
observer.observe(document.querySelector('.target'));
第三方库方案
考虑使用现成解决方案:
- vue-scroll-sync
- vue-sync-scroll
- custom-scroll
安装示例:
npm install vue-scroll-sync
使用示例:
import { ScrollSync } from 'vue-scroll-sync'
export default {
components: { ScrollSync },
template: `
<scroll-sync>
<div class="area1">内容1</div>
<div class="area2">内容2</div>
</scroll-sync>
`
}
以上方案可根据具体场景选择或组合使用,注意处理边界情况和性能优化。







