passive事件始末

不知道从什么时候开始,在谷歌浏览器中,我们无法正常的从touchstart, touchemove等事件中调用preventDefault函数了。经过一段时间的资料查询,发现这一切都源于浏览器对scroll(滑动页面)的一个优化。

在浏览器中,为了让滑动滚动条能够在沉重js环境下顺畅运行,滚动屏幕是通过多线程来实现的。但这一个优化有可能会因为一系列的touchstart给毁掉。因为,任何touchstart中都有可能发生preventDefault函数的调用,而这个函数就会终止掉滚动屏幕的操作。这就会发生一个线程在运行过程中,不断的检测另外一个线程有没有发生某个事件。这毫无疑问是对性能的大打折扣。

为了更好的优化这个性能,谷歌浏览器给touchstart, touchmove, touchend等函数都默认为passive事件。除非你“显示”的通过addEventListener函数,给touchstart的回调定义为passive=false。例如:

dom.addEventListener('touchstart', onTouchStart, {passive: false})

通过以上方式绑定的onTouchStart函数中才可以调用event.preventDefault()

react-ace 9.0.0与ace-builds1.4.11的应用

react-ace库在2周前做了最新的更新,然而其readme却没有跟着一起更新,因此如果仍然按照该说明使用,会有一些问题。

  1. webpack编译会导致ace的worker找不到位置的错误,解决方案是,在引入react-ace后,引入以下模块
    import "ace-builds/webpack-resolver";
  2. enableBasicAutocompletion和enableLiveAutocompletion的配置会出现失效的问题,如果没有引入以下两个模块的话:
    import "ace-builds/src-min-noconflict/ext-searchbox";
    import "ace-builds/src-min-noconflict/ext-language_tools";

javascript 大运算量 vs 顺滑UI 的一种解决方案

有时候不可避免需要在前端进行比较重的运算,而如此沉重的运算一般来说对ui体验,是会有很大影响的,它甚至可能导致前端在一段时间内,什么响应和操作都无法进行。一般来说,前端的线程是单线程的。当然,目前前端的worker多线程也开始广泛应用了,但多线程又涉及到一个线程间传送数据的问题。当然,多线程肯定也是一个解决此问题的一个重要方案。而本文要提到的是另外一种解决方案。

我们可以把运算量切片,然后把运算了放到requestAnimationFrame中去运行。此方法也并非我原创,此博文也介绍了此方法的应用:

We now have a clean way of running our heavy function without freezing the UI. Furthermore, since we know the number of slices in advance, we could update a counter of finished slices inside the requestAnimationFrame callback which would provide a simple and accurate progress indicator.

采用这种方案的关键在于两个点,第一,我们需要如何去控制每一步的运算量。第二,把每一部的运算结果保存起来,以此在最后才能叠加所有的操作。