问题描述
这个问题是关于触摸、滚动和交叉观察者回调的执行顺序。
我有一个简单的移动网络应用程序,它有一个可滚动的列表视图,其中每个项目的高度为 100 像素,并且我在视口上放置了交叉点观察者,但顶部边距为 -100px( rootMargin: "-100px 0px 0px 0px"
)。
以这种方式完成,以便我的列表项一向上滚动就可以观察到。
交点观察者是这样的:
const io = new IntersectionObserver(viewportBottomObserverCallback, {
root: null,
rootMargin: "-100px 0px 0px 0px",
threshold: [0, 1]
})
我有 touchmove 处理程序、滚动处理程序和交叉点观察者回调。
现在,只要我触摸并向上滑动,我就会看到这些处理程序/回调的执行行为一致。
首先onTouchMove
,然后onScroll
,最后调用viewportBottomObserverCallback
。
总是这样吗?
这个问题很重要,因为如果我知道这些 DOM 事件总是按这个顺序调用,那么我的代码将变得非常确定。
通常,任何其他 DOM 事件都不是这种情况。
为了更好地可视化它,我附上了我的 chrome 分析器的屏幕截图。 蓝色里面的部分是我的交叉点观察者回调。
编辑:
我正在以响应模式在 Chrome 上对此进行测试,设备为 iPhone 6/7/8。
还有一个问题:任务(交叉观察者)到事件循环的计算和排队是否只有在update layer tree
完成后才发生,特别是这个任务 - ?
1楼
总结 -
所有微任务都在任何其他事件处理、渲染或任何其他宏任务发生之前完成。 这保证了应用程序在微任务之间基本相同(没有鼠标坐标变化,没有新的网络数据等)。
所以是的! 它是确定性的。
退后一步,浏览器使用事件循环在脚本、渲染、绘画、网络和事件之间切换。 在事件循环的每一轮中,执行一个宏任务。 宏任务是诸如 UI 事件(鼠标移动)、DOM 操作和 setTimeout 之类的操作。 微任务在宏任务出队后运行。 所以像IntersectionObserver和Promise.resolve这样的事情在渲染和绘制之前发生在 Microtask 队列中。