我不明白为什么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>

Javascript相关问答推荐

为什么getRecord()会因为与_logger相关的错误而失败?(使用Hedera SDK)

fs. writeFile()vs fs.writeFile()vs fs.appendFile()

JQuery. show()工作,但. hide()不工作

如何在Javascript中的控制台上以一行形式打印循环的结果

如何为我的astro页面中的相同组件自动创建不同的内容?

Promise Chain中的第二个useState不更新

Chromium会将URL与JS一起传递到V8吗?

使用LocaleCompare()进行排序时,首先使用大写字母

实现JS代码更改CSS元素

闭包是将值复制到内存的另一个位置吗?

如何创建返回不带`new`关键字的实例的类

让chart.js饼图中的一个切片变厚?

处理TypeScrip Vue组件未初始化的react 对象

如何在独立的Angular 应用程序中添加Lucide-Angel?

谷歌饼图3D切片

为什么我的SoupRequest";被重置为初始值,以及如何修复它?

在Java脚本中构建接口的对象

为什么当雪碧的S在另一个函数中时,Phaser不能加载它?

扩散运算符未按预期工作,引发语法错误

Node.js的Fetch()调用总是创建新的Express会话