学会一行 CSS 即可提升页面滚动性能
一般情况下 CSS 并不会影响 JS 事件,但有一个 CSS 属性则比较特殊,那就是 pointer-events
,它可以用来规避鼠标事件,其中大部分属性值只适用于 SVG(可缩放矢量图形)操作,而我们只需要关注其 none
属性值,该值表示鼠标事件“穿透”该元素并且指定该元素“下面”的任何东西。
我们经常会碰到类似设置半透明遮罩的需求,通常是绝对定位一个 div 盖在元素上方,这时遮罩层的鼠标事件优先级会更高,使得打上遮罩的元素无法进行正常交互行为,此时只需给遮罩设置
pointer-events: none;
即可"穿透"遮罩与元素交互。
重点来了,既然该属性可以阻止元素成为鼠标事件,那么修改页面该属性值为 none
,就能避免在滚动时鼠标频繁触发包括hover
在内的任何鼠标事件,从而提升了页面滚动时的性能。
使用滚动监听事件可实现灵活控制:
如果是移动端网页,没有鼠标事件是不是就不能用上面的属性来优化滚动了呢?确实不可以,但移动端则有另外一个特殊属性具有异曲同工之处,那就是 touch-action
。
顾名思义,该属性是用于设置触摸屏如何操纵元素区域动作,同样的,touch-action
可以禁用浏览器在移动端处理手势的事件,进而提高页面滚动性能,同时它还能解决移动端 点击延迟问题(很多人可能只知道 viewport meta 标签或 fastclick)。不过需要注意的是,虽然该属性也有 none
值,但在这里并不适用,因为"滚动"也属于手势的一种,应该使用 manipulation
这个值,意为只允许进行滚动和持续缩放操作,也就相当于禁用了其他页面手势。
全局生效要写在 html 上:
类似的,如果移动端有自定义拖动的需求,也可以用这个 CSS 来优化性能,当我们需要完全阻止原生 touch 事件时 JS 设置 touch-action
为 none
,不需要再还原即可。
可能有的朋友就会问了,如果我们在 touchstart
或 touchmove
事件中用 event.preventDefault()
阻止系统默认事件,不就可以阻止手势操作吗?
preventDefault()
能阻止默认事件,当然包括手势事件,但是如果在 windiw
document
body
这些地方直接使用,不仅没有效果,浏览器还会出现红字严重报错,这是因为 touch
监听事件都是先进行了"触摸"才能执行回调,如果需要阻止默认事件,那么就必须在触摸开始前就检查是否需要阻止,滑动响应的优先级反而降低了,Google 为了保证滑动流畅性就默认取消了这一机制。所以从 chrome56 开始,如果你在全局 touch
事件中不声明这是"非被动"操作,那么 chrome 浏览器会默认不执行并报错。
注:在 Vue 中有这样一个修饰符讲的也是同一件事情
而这个时候 touch-action
就发挥作用了,它相当于先声明了元素的可用触摸事件,这样浏览器就不会报错了,preventDefault()
也不会影响到触摸的事件,这两者可以结合来使用。(touch-action: none
会阻止任何触摸行为,但 touch 事件是正常触发的)
相关资料传送门:
以上就是文章的全部内容,希望对你有所帮助!如果觉得文章写的不错,可以点赞收藏,也欢迎关注,我会持续更新更多前端有用的知识与实用技巧,我是茶无味de一天,希望与你共同成长~
版权声明: 本文为 InfoQ 作者【茶无味的一天】的原创文章。
原文链接:【http://xie.infoq.cn/article/12c14e5f854e0da52fb21ea80】。文章转载请联系作者。
评论