背景:最近在微官网项目时,有一个优化问题,需要阻止微信H5页面下滑时背景出现域名,在网上查到的解决方法大多数是直接阻止掉touchmove的默认事件,如下:
document.addEventListener('touchmove', function (evt) {
evt.preventDefault()
}, { passive: false })
这样确实阻止掉了touchmove的默认事件,但如果页面中有元素需要滚动,而这个滚动又是基于overflow属性进行设置的,那这个滚动同样也就不能触发了。
然后呢,又在网上一通搜索,发现可以针对性的对元素阻止touchmove默认事件,
如下:
var overscroll = function(el) {
el.addEventListener('touchstart', function() {
var top = el.scrollTop
, totalScroll = el.scrollHeight
, currentScroll = top + el.offsetHeight;
if(top === 0) {
el.scrollTop = 1;
} else if(currentScroll === totalScroll) {
el.scrollTop = top - 1;
}
});
el.addEventListener('touchmove', function(evt) {
if(el.offsetHeight < el.scrollHeight)
evt._isScroller = true;
});
}
//下面一行代码就是防止元素被禁用掉touchmove的默认事件的,对于通过使用overflow进行滑动的元素使用
overscroll(document.querySelector('.scroll'));
document.body.addEventListener('touchmove', function(evt) {
if(!evt._isScroller) {
evt.preventDefault();
}
})
以上方法可行,很不错,但对于一个已经成型的项目,且有大量元素使用overflow进行滚动的项目来说,要去进行一一排查,工作量无疑是大的,且有可能会有遗漏的元素。
因此,我再以上的基础上,对这个方法进行了完善。
//该方法用来遍历元素,遍历至根元素,查看每一个元素上的overflow属性是否设置滚动,
//针对设置了滚动的元素调用overscroll方法
function toRoot (dom) {
const isScroll = window.getComputedStyle(dom, null).overflow
// console.log(isScroll, dom)
if (dom.className === 'el-table__fixed') {
return
}
if (isScroll.includes('auto') || isScroll.includes('scroll')) {
overscroll(dom)
// return
}
if (dom.getAttribute('id') === 'app') {
return
}
if (dom.tagName === 'BODY') {
return
}
toRoot(dom.parentNode)
}
export const overscroll = function (el) {
//以下属性是用来判断手指滑动的方向,毕竟有的元素只能左右滑,有的元素只能上下滑
let startX, startY, moveEndX, moveEndY, X, Y
el.addEventListener('touchstart', function (e) {
startX = e.touches[0].pageX
startY = e.touches[0].pageY
const top = el.scrollTop
const totalScroll = el.scrollHeight
const currentScroll = top + el.offsetHeight
if (top === 0) {
el.scrollTop = 1
} else if (currentScroll === totalScroll) {
el.scrollTop = top - 1
}
})
el.addEventListener('touchend', (e) => {
moveEndX = 0
moveEndY = 0
})
el.addEventListener('touchmove', function (evt) {
if (!moveEndX && !moveEndX) {
moveEndX = evt.changedTouches[0].pageX
moveEndY = evt.changedTouches[0].pageY
X = moveEndX - startX
Y = moveEndY - startY
console.log(X, Y, moveEndX, startX, moveEndY, startY)
}
if (el.offsetHeight < el.scrollHeight && Math.abs(Y) > Math.abs(X)) {
evt._isScroller = true
}
if (el.offsetWidth < el.scrollWidth && Math.abs(X) > Math.abs(Y)) {
evt._isScroller = true
}
})
}
document.addEventListener('touchstart', function (evt) {
const isScroll = window.getComputedStyle(evt.target, null).overflow
const dom = evt.target
if (isScroll.includes('auto') || isScroll.includes('scroll')) {
overscroll(dom)
return
}
toRoot(dom.parentNode)
}, { passive: false })
document.addEventListener('touchmove', function (evt) {
if (!evt._isScroller) {
evt.preventDefault()
}
}, { passive: false })
将以上代码,用在项目的main.js中,即可解决掉微信H5下拉出现域名的问题,当然,这个方法好像也不能完全的阻止下拉出现域名的问题,当页面未加载完,或者连续快速滑动时,也会导致,但能够极大的减少95%的下拉问题。
ps:如有不足和优化,请在评论区指出