我不明白为什么Mutations 观察者回调或promise 使用微任务队列来确定优先级.
比如用户点击等等,与宏任务队列一起处理.为什么会做出这个决定?像点击这样的用户操作难道不是比像promise这样的开发人员操作更重要吗?
对此有什么具体的解释或文件吗?或者这只是JS创建时JS演变的一部分?当时很少有多核的通用计算机,所以没有人考虑太多,后来,我们陷入了传统支持的行为.
我不明白为什么Mutations 观察者回调或promise 使用微任务队列来确定优先级.
比如用户点击等等,与宏任务队列一起处理.为什么会做出这个决定?像点击这样的用户操作难道不是比像promise这样的开发人员操作更重要吗?
对此有什么具体的解释或文件吗?或者这只是JS创建时JS演变的一部分?当时很少有多核的通用计算机,所以没有人考虑太多,后来,我们陷入了传统支持的行为.
MutationObserver的回调应该在更新DOM的渲染之前执行,这发生在macrotask的结尾,否则如果你在回调中更新DOM,会出现闪烁/屏幕撕裂,因为回调将在渲染之后在另一个macrotask中调用.
另一方面,您可以使用许多Mutations 来更改DOM同步.如果MutationWatch是同步的,则会导致过多的事件,并可能在回调中产生额外的Mutations ,从而导致无限递归.
有时候,即使MutationObserver的rectuc性质,你也需要在回调中克服递归.
这里我们将style属性更改2次.想象一下,如果props 的数量会更大,每个props 都会触发MutationObserver.
考虑一下,当你在回调过程中,DOM在macrotask的同步阶段被"稳定"了.所以你可以更好地控制以后发生的事情.
在下面的代码中,很明显,观察回调与其他微任务同步. 如果你大部分是水平移动鼠标光标,那么第一个变化发生,并且立即安排观察回调.进一步的DOM变化只是向传递给回调的变化列表添加变化.
回到我们的回调,判断X和Y轴上的黑色标记,我们在观察回调中改变它们的样式.如果回调是在另一个macrotask中执行的,则标记将与指针圈不同步,因为标记和指针将在它们的同步状态下单独呈现,并且在macrotask之间指针可能会有额外的变化.
document.addEventListener('mousemove', e => {
queueMicrotask(()=>console.log('microtask before mutations'));
$pointer.style.left = e.x + 'px';
console.log('left mutated');
queueMicrotask(()=>console.log('microtask between mutations'));
$pointer.style.top = e.y + 'px'
console.log('top mutated');
queueMicrotask(()=>console.log('microtask after mutations'));
});
new MutationObserver(()=>{
console.log(`moved ${$pointer.style.left} ${$pointer.style.top}`);
const {left, top} = $pointer.getBoundingClientRect();
$xaxis.style.left = left + 'px';
$yaxis.style.top = top + 'px';
}).observe($pointer, {attributes:true});
.pointer{
width:16px;
height:16px;
border: 1px solid gray;
border-radius:50%;
position: fixed;
margin: -8px 0 0 -8px;
}
.axis-mark{
width:16px;
height:16px;
background:black;
left: 0;
top:0;
position: fixed;
}
<div class="pointer" id="$pointer"></div>
<div class="axis-mark" id="$xaxis"></div>
<div class="axis-mark" id="$yaxis"></div>