在 MutationObserver for 循环中运行一次函数

Run a function once in MutationObserver for loop

提问人:bobby 提问时间:9/20/2023 更新时间:9/20/2023 访问量:26

问:

我正在使用 MutationObserver 来观察该类的任何元素是否更改了其内联样式。例如,它可能看起来像这样:在页面上,有两个带有此类的方块,因此我需要观察它们中的任何一个是否发生变化。如果其中一个或两个都发生了变化,我想运行该函数。这是我正在研究的基础。last-move<square class="last-move" style="transform: translate(204px, 68px);"></square>last-movepieceMoved()

function observeNewMove() {
  const targetElements = document.querySelectorAll('.last-move');

  targetElements.forEach((targetElement) => {
    const observer = new MutationObserver((mutationsList, observer) => {
      for (const mutation of mutationsList) { // For loop to see if any of the two elements have changed.
        if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
            pieceMoved(); // Function to be called once.
        }
      }
    });

    observer.observe(targetElement, { attributes: true });
  });
}

问题变成了至少调用两次,因为大多数时候带有类的两个方块都会改变样式,但我希望被调用一次,即使 for 循环运行两次迭代。pieceMoved()last-movepieceMoved()

总而言之,我希望只运行一次,即使 for 循环迭代超过此次数。pieceMoved()

我尝试使用具有局部和全局变量的不同类型的标志系统,从 false-true 开始,然后是 true-false,以及介于两者之间的所有内容。下面是一个示例

function observeNewMove() {
  let flag = false;
  const targetElements = document.querySelectorAll('.last-move');

  targetElements.forEach((targetElement) => {
    const observer = new MutationObserver((mutationsList, observer) => {
      for (const mutation of mutationsList) { // For loop to see if any of the two elements have changed.
        if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
            if (flag) {
                pieceMoved(); // Function to be called once.
            }
            flag = true;
        }
      }
    });

    observer.observe(targetElement, { attributes: true });
  });
}

这将在第一次被调用时起作用,但不适用于后续移动(因为不会再次调用,如果我理解正确的话,它会永远运行,直到断开连接)。更改 的位置将导致永远不会被调用( 总是,或者一直被调用两次 ( 总是)。observeNewMove()observeNewMove()let flag = false;pieceMoved()flag = falseflag = true

javascript for-loop 标志 mutation-observers

评论


答:

0赞 Konrad 9/20/2023 #1
function observeNewMove() {
  const targetElements = document.querySelectorAll('.last-move');

  targetElements.forEach((targetElement) => {
    const observer = new MutationObserver((mutationsList, observer) => {
      // declare it before loop
      let once = false
      for (const mutation of mutationsList) { // For loop to see if any of the two elements have changed.
        if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
            // change it in the loop
            once = true
        }
      }
      // check it after the loop
      if (once) {
        pieceMoved(); // Function to be called once.
      }
    });

    observer.observe(targetElement, { attributes: true });
  });
}

评论

1赞 bobby 9/21/2023
我很遗憾地说,这种方法不起作用,因为仍然在里面.里面的所有代码将运行两次。pieceMoved()targetElements.forEach((targetElement) => { ... }if (once) { ... }