先来放图看效果
在一切开始前我们先来测试原生的js实现的方法
1.新建一个test.html文件
要求在html中创建两个div,同等固定高度的,并随意填充任意的text,p div等大量超出div的高度。
2.需求分析
我们的目的是尽量左边滚动右边同步滚动,而右边滚动左边却不滚动。代码如下。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>原生滚动方式</title>
</head>
<body>
<div id="app">
<div class="scroll-left" id="left">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<div class="scroll-right" id="right">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</div>
</body>
<script>
//左div绑定滚动事件
let left=document.getElementById('left');
let right=document.getElementById("right");
left.onscroll=(e)=>{
console.log("滚动事件",e.target.scrollTop); //scrollTop即为元素滚动的高度’‘
console.log("打印此时右边的滚动高度",right.scrollTop);
//同步,即吧左边的scrollTop赋值给右边的scrollTop
/******* !!!!!!!!!!!!!!!!!!!!!!!!******/
right.scrollTop=e.target.scrollTop;
}
</script>
<style scoped>
#app{
display: flex;
}
.scroll-left,
.scroll-right{
width:40%;
height:600px;
}
.scroll-left{
background-color: antiquewhite;
overflow: auto;
}
.scroll-right{
background-color: #c3faff;
overflow: auto;
}
.item{
height:200px;
width:90%;
margin-bottom: 50px;
}
.scroll-left .item{
background-color: brown;
}
.scroll-right .item{
background-color: coral;
}
</style>
</html>
从代码上,我只是把左右两边的滚动条打开overflow
为auto
,接着在js中对左边的div绑定scroll
事件,事件中把左侧的垂直滚动的距离scrollTop
直接给右侧的垂直滚动距离,而右侧不绑定任何事件,这样,滚动右侧的滚动条可实现右侧的同步,而右侧的滚动对左侧没有任何的影响
3.vue.js的设计方案
明确了原生的js实现方式,我们来用vue.js复现并美化一下。
思路是一样的,唯一不同的是采用vuescroll的回调函数来控制。
请查看handle-scroll事件和scrollTo API
参考代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue 双开div同步滚动测试</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vuescroll"></script>
<div id="app">
<vue-scroll :ops="left" class="left-scroll" @handle-scroll="leftScroll" ref="v-left">
<div class="left" ref="left">
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
</div>
</vue-scroll class="right-scroll" @handle-scroll="rightScroll" ref="v-right">
<vue-scroll>
<div class="right" ref="right">
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
<div class="item-block"></div>
</div>
</vue-scroll>
</div>
</body>
<script>
const vs=new Vue();
const vm = new Vue({
el: '#app',
data() {
return {
msg: 'hello world!',
//left是左侧的vuescroll参数
left:{
vuescroll: {
mode:'native',
//locking:true
},
scrollPanel: {
speed:400,
//scrollingX:false,
//scrollingY:true
scrollingX:false
},
rail: {
keepShow:true,
opacity:0.7,
background:'rgb(229, 229, 229)'
},
bar: {
keepShow:true
}
},
leftCH:0
}
},
created() {},
//注意 refs在挂载后才生效,故下面的代码放在mounted中
mounted() {
let rightScrollTop = this.$refs["right"].scrollTop
let that = this; //因为下面函数的this不再指向此vue实例
this.$refs["left"].onscroll = function (e) {
// console.log(this.scrollTop)
that.$refs["right"].scrollTop = this.scrollTop
//console.log(that.$refs["right"].scrollTop)
}
vs.$on("left-change",(e,arg)=>{
//console.log("事件监听器",e,that.$children[1])
});
},
methods:{
//vuecroll的回调函数,实现同步
leftScroll(vertical,horizontal,nativeEvent){
//console.log(vertital,horizontal,nativeEvent) 全部打印
//console.log(vertital) //部分打印,高度变化
// console.log(this.$refs['v-right'])//打印得到undefined
let that=this;
let change=vertical.scrollTop-this.leftCH;
this.leftCH=vertical.scrollTop;
console.log(change)
this.$children[1].scrollTo({
y:vertical.scrollTop
},0)
vs.$emit("left-change",vertical.scrollTop)
},
rightScroll(vertital,horizontal,nativeEvent){
}
},
});
</script>
<style scoped>
#app {
height: 550px;
/* overflow: hidden;*/
}
#app {
display: flex;
}
.left,
.right {
height: fit-content;
}
.left {
/*width: 40%;*/
background-color: aquamarine;
/*overflow: auto;*/
}
.right {
/*width: 40%;*/
background-color: red;
/*overflow: auto;*/
}
.left .item-block {
height: 300px;
width: 80%;
background-color: yellow;
margin-top: 20px;
}
.right .item-block {
height: 300px;
width: 80%;
background-color: rgb(0, 225, 255);
margin-top: 20px
}
.left-scroll .__rail-is-horizontal{
display: none!important;
}
</style>
</html>
关键部分已经写好注释了,具体的API方法和回调懒得说,说明自行参看附上的链接。
如有问题欢迎下方留言或者邮箱联系zero@zerotower.xyz
Good Bye ~