开发中遇到这样一个需求,有两个div,当页面滚动时,第一个div隐藏,当页面停止滚动时,div显示,当滚动大于某个值时,第二个div显示(这种情景多用于商品列表,当用户点击按钮时,回到最顶部)
首先先在data中定义变量(isshow:控制第一个div;btnFlag:控制第二个div)
mounted() {
window.addEventListener("scroll", this.scrollToTop);
},
beforeDestroy() {
//离开页面时取消监听,防止内存泄露
window.removeEventListener("scroll", this.scrollToTop);
},
watch: {
scrollTop(newValue, oldValue) {
setTimeout(() => {
if (newValue == window.scrollY) {
//滚动结束
this.isshow = true;
//延时执行后当newValue等于window.scrollY,代表滚动结束
this.oldScrollTop = newValue; //每次滚动结束后都要给oldScrollTop赋值
}
}, 20); //必须使用延时器,否则每次newValue和window.scrollY都相等,无法判断,20ms刚好大于watch的侦听周期,故延时20ms
if (this.oldScrollTop == oldValue) {
//滚动开始
//每次滚动开始时oldScrollTop与oldValue相等
this.isshow = false;
}
}
},
methods:{
backTop() {
let timer = setInterval(() => {
let ispeed = Math.floor(-this.scrollTop / 5);
document.documentElement.scrollTop = document.body.scrollTop =
this.scrollTop + ispeed;
if (this.scrollTop === 0) {
clearInterval(timer);
}
}, 16);
},
// 为了计算距离顶部的高度,当高度大于300显示回顶部图标,小于700则隐藏
scrollToTop() {
let scrollTop =
window.pageYOffset ||
document.documentElement.scrollTop ||
document.body.scrollTop;
this.scrollTop = scrollTop;
if (scrollTop > 300) {
this.btnFlag = true;
} else {
this.btnFlag = false;
}
}
}
在电脑调式的时候,效果很好。
在安卓上效果也还行,但是在ios上会存在第一个div在停止滚动之后,闪烁几下在显示。
百度了一下,说这是scroll在ios上的通病~
后来我觉得用better-scroll,这个插件已经很成熟了,在安卓和ios上表现都很好,应该能够解决我的问题,加上我之前项目本身就引入了better-scroll,所以我就抱着试试的态度
先引入better-scroll
import BScroll from 'better-scroll'
再data中定义
scrollY:''
在mounted中初始化better-scroll,用setTimeout或者this.$nextTick等到dom渲染成功了再初始化
this.$nextTick(() => {
this.initScroll();
});
methods中
initScroll() {
this.$nextTick(() => {
if (!this.$refs.listWrapperL) { //如果没有获取到dom就不继续,防止找不到dom报错
return;
}
//配置: 可根据个人需求
this.listScroll = new BScroll(this.$refs.listWrapperL, {
probeType: 3, // 是否会截流scroll事件
scrollY: true, // 是否开启Y轴滚动方向
click: true, // 是否开启点击事件
useTransition: false, // 防止iphone微信滑动卡顿
bounce: true, // 是否启用回弹动画效果
momentumLimitDistance: 5 // 符合惯性拖动的最小拖动距离
});
this.listScroll.on("scroll", pos => {
this.isshow = false; //控制第一个div滚动是隐藏
// 使用abs绝对值(否则 pos.y拿到值是负数)
this.scrollY = Math.abs(Math.round(pos.y));
if (this.scrollY >= 300) {
this.btnFlag = true; //控制第二个div滚动到一定距离显示
} else {
this.btnFlag = false; //控制第二个div滚动到一定距离隐藏
}
});
this.listScroll.on("scrollEnd", pos => {
console.log("页面停止");
this.isshow = true; //控制第一个div滚动是显示
});
});
},
现在我们两个div都能满足需求的动态显示与隐藏了,现在还差一个功能,就是点击第二个div的时候要回到页面顶部
backTop() {
this.listScroll.scrollTo(0, 0, 1000);
}
我用下来遇到的问题就是页面滚动不了?
然后看了官方文档,说内容高度一定要大于外面的盒子高度才能滚动,这也是better-scroll滚动的原理。
于是我那些我的调式工具,一个块一个块点,没问题啊,我的内容高度已经是超出外面盒子的高度了,即使我给外面的盒子设置400px的高度,依旧不能滚动。然后我不知道是在哪里看到的,说better-scroll只作用于第一个div,然后我再看看我的html结构
样式代码
.listWrapperL {
width: 100%;
height: 100%;
overflow: hidden;
-webkit-overflow-scrolling: touch;
}
最后在页面离开的时候一定要销毁一下better-scroll,防止内存泄露