乐趣区

关于前端:学会一行CSS即可提升页面滚动性能

个别状况下 CSS 并不会影响 JS 事件,但有一个 CSS 属性则比拟非凡,那就是 pointer-events,它能够用来躲避鼠标事件,其中大部分属性值只实用于 SVG(可缩放矢量图形)操作,而咱们只须要关注其 none 属性值,该值示意鼠标事件“穿透”该元素并且指定该元素“上面”的任何货色。

咱们常常会碰到相似设置半透明遮罩的需要,通常是相对定位一个 div 盖在元素上方,这时遮罩层的鼠标事件优先级会更高,使得打上遮罩的元素无奈进行失常交互行为,此时只需给遮罩设置 pointer-events: none; 即可 ” 穿透 ” 遮罩与元素交互。

重点来了,既然该属性能够 阻止元素成为鼠标事件 ,那么批改页面该属性值为 none,就能防止在滚动时鼠标频繁触发包含hover 在内的任何鼠标事件,从而晋升了页面滚动时的性能。

body {pointer-events: none;}

应用滚动监听事件可实现灵便管制:

let timer = null
window.addEventListener("scroll", function () {
    document.body.style.pointerEvents = 'none'; // 滚动时禁用鼠标事件
    if (timer) {clearTimeout(timer) }
    timer = setTimeout(() => {document.body.style.pointerEvents = 'auto'; // 开释}, 100);
})

如果是挪动端网页,没有鼠标事件是不是就不能用下面的属性来优化滚动了呢?的确不能够,但挪动端则有另外一个非凡属性具备殊途同归之处,那就是 touch-action

顾名思义,该属性是用于设置触摸屏如何操纵元素区域动作,同样的,touch-action 能够禁用浏览器在挪动端解决手势的事件,进而进步页面滚动性能,同时它还能解决挪动端 点击提早问题 (很多人可能只晓得viewport meta 标签或fastclick)。不过须要留神的是,尽管该属性也有 none 值,但在这里并不实用,因为 ” 滚动 ” 也属于手势的一种,应该应用 manipulation 这个值,意为只容许进行滚动和继续缩放操作,也就相当于禁用了其余页面手势。

全局失效要写在 html 上:

html {touch-action: manipulation;}

相似的,如果挪动端有自定义拖动的需要,也能够用这个 CSS 来优化性能,当咱们须要齐全阻止原生 touch 事件时 JS 设置 touch-actionnone,不须要再还原即可。

// 在须要时被动触发对全局的手势禁用
document.documentElement.style.touchAction = 'none'
// 或者独立禁用某一片区域的手势操作
document.getElementById('xxx').style.touchAction = 'none'
// 不须要时还原,例如在抬手事件中解决
document.addEventListener('touchend', function (event) {document.documentElement.style.touchAction = 'manipulation' // 或 auto});

可能有的敌人就会问了,如果咱们在 touchstarttouchmove 事件中用 event.preventDefault() 阻止零碎默认事件,不就能够阻止手势操作吗?

preventDefault()能阻止默认事件,当然包含手势事件,然而如果在 windiw document body 这些中央间接应用,不仅没有成果,浏览器还会呈现红字重大报错,这是因为 touch 监听事件都是先进行了 ” 触摸 ” 能力执行回调,如果须要阻止默认事件,那么就必须在触摸开始前就查看是否须要阻止,滑动响应的优先级反而升高了,Google 为了保障滑动流畅性就默认勾销了这一机制。
所以从 chrome56 开始,如果你在全局 touch 事件中不申明这是 ”非被动“ 操作,那么 chrome 浏览器会默认不执行并报错。

window.addEventListener('touchmove', e => e.preventDefault()) // 有效,并报错
window.addEventListener('touchmove', e => e.preventDefault(), {passive: false}) // 无效

注:在 Vue 中有这样一个修饰符讲的也是同一件事件

而这个时候 touch-action 就发挥作用了,它相当于先申明了元素的可用触摸事件,这样浏览器就不会报错了,preventDefault() 也不会影响到触摸的事件,这两者能够联合来应用。(touch-action: none 会阻止任何触摸行为,但 touch 事件是 失常触发 的)

// 以下代码成果:在滑动时阻止零碎默认事件,且页面能够失常滑动
document.documentElement.style.touchAction = 'manipulation'
window.addEventListener('touchmove', e => e.preventDefault())
// 将 manipulation 值改为 none,就能够齐全阻止滑动默认事件,看状况来,毕竟 touch-action 还有很多可选值

相干材料传送门:

MDN – CSS – pointer-events

MDN – CSS – touch-action

以上就是文章的全部内容,心愿对你有所帮忙!如果感觉文章写的不错,能够点赞珍藏,也欢送关注,我会继续更新更多前端有用的常识与实用技巧,我是茶无味 de 一天,心愿与你独特成长~

退出移动版