单击事件停止 MutationOberserver

Stop MutationOberserver on click event

我有一个动态的 DOM 结构,其中节点始终被插入和删除,以便对新节点做出反应我使用的是 MutationObserver,当用户单击 Button 时它会被激活。每次用户单击该按钮时,MutationObserver 都会 运行 两个函数,当我观察到的 DOM 结构发生变化时,这些函数将保持 运行ning。

我想要做的是在用户再次单击按钮时立即断开 MutationObservers(假设第一次单击然后对元素进行排序,再次单击并停止对元素进行排序)。每次用户单击按钮时,我都会传递一个布尔值 (goSortDom)(如果为真,请执行操作并观察,如果为假,则停止观察)。问题是,当我尝试在 goSortDom=false 时断开观察者的连接时,它们永远不会断开连接,并且函数将保持 运行ning.

我对 mutationObservers 很陌生,所以我不知道我的方法是否是一种不好的做法,这就是为什么我也非常感谢对此的评论。

$(document).ready(function () {
  // Function 1: Assign Priorities
  function assignChatPriority(arrayParent) {
     //Assign Priorities
     //Observe if time change, if change re-assign priority to dom node
     timeInQueueDomObserver.observe(
     $(incomingChat).find(".time_cell")[0],
     configtimeInQueue
  }

  // Function 2: Reorder DOM
  function orderIncomingChats() {
    //Reorder DOM save DOM elements to Array
    //Replace original DOM with new sorted DOM 
  }

  //Declaring DOM Observers for Time in Queue and DOM container dynamics
  var incomingChatsDomObserver = new MutationObserver(function (mutations) {
    mutations.forEach(function (mutation) {
      if (mutation.addedNodes.length) {
        for (let i = 0; i < mutation.addedNodes.length; i++) {
          if (
            mutation.addedNodes[i].attributes["data-priority"] === undefined
          ) {
            runExtensionFunctions();
          }
        }
      }
    });
  });
  var timeInQueueDomObserver = new MutationObserver(function (mutations) {
    mutations.forEach(function (mutation) {
      if (
        mutation.addedNodes.length === 1 &&
        mutation.addedNodes[0].nodeType === Node.TEXT_NODE &&
        mutation.removedNodes.length === 1 &&
        mutation.removedNodes[0].nodeType === Node.TEXT_NODE
      ) {
        runExtensionFunctions();
      }
    });
  });

  //Obervers Configuration
  let configChatsContainer = {
    childList: true,
  };
  let configtimeInQueue = {
    childList: true,
  };
  if (goSortDom) {
    //boolean is true go ahead run functions and observe
    assignChatPriority(incomingChatsRows);
    orderIncomingChats();
    incomingChatsDomObserver.observe(
      incomingChatsContainer[0],
      configChatsContainer
    );
  } else {
    //disconnect observers: WON'T WORK
    incomingChatsDomObserver.disconnect();
    timeInQueueDomObserver.disconnect();
  }
}

您的代码似乎无法识别 (goSortDom) 单击事件。您是否尝试过将该代码字符串添加到您的按钮单击事件中? Vue.js 框架可能非常适合您的要求。除此之外,我能告诉你的和你知道的一样。当 dom 元素动态改变时,Javascript 行为非常奇怪。我有一个应用程序,该应用程序的选择数量呈指数级增长,这些选择是根据之前的选择加载的。每次加载新信息时,我都必须特别注意用于操作数据的选择器。否则,无论 Id 或 class 选择器如何,JS 都无法使用新导入的数据。我还必须使用 .on( events [ selector ] [ data ] ) Javascript 函数而不是 .click() jquery 函数来完成工作。特别是确保填写了选择器信息。
$("#myDiv").on('click', '.MyDivClass', function(){'Select All and return information'};

您在传递给 .ready() 的函数中初始化并处理 MutationObserver 的 incomingChatsDomObservertimeInQueueDomObserver。我没有看到外部参考。如果是这种情况,if (goSortDom) 只会对初始化的 MutationObserver 进行一次评估。之后,函数结束,引用丢失。再次调用该函数会创建 new MutationObserver,并且 disconnect() 调用将引用那些新的 MutationObserver,而不是已经观察到的旧 MutationObserver!

难道你想达到的目的是把MutationObserver的初始化和引用移到这个函数外面去用?或者可能会断开 MutationObservers 内部的连接?

让我试一试。由于这不是完整的代码,我无法自己测试它:

  1. 想法(移动参考):
// ANSWERER: Now the references are outside the ready function. If the ready function is done, this references still exist. 
  //Declaring DOM Observers for Time in Queue and DOM container dynamics
  var incomingChatsDomObserver = new MutationObserver(function (mutations) {
    mutations.forEach(function (mutation) {
      if (mutation.addedNodes.length) {
        for (let i = 0; i < mutation.addedNodes.length; i++) {
          if (
            mutation.addedNodes[i].attributes["data-priority"] === undefined
          ) {
            runExtensionFunctions();
          }
        }
      }
    });
  });
  var timeInQueueDomObserver = new MutationObserver(function (mutations) {
    mutations.forEach(function (mutation) {
      if (
        mutation.addedNodes.length === 1 &&
        mutation.addedNodes[0].nodeType === Node.TEXT_NODE &&
        mutation.removedNodes.length === 1 &&
        mutation.removedNodes[0].nodeType === Node.TEXT_NODE
      ) {
        runExtensionFunctions();
      }
    });
  });

// ANSWERER: This is now possible  
function disconnectObservers() {
    incomingChatsDomObserver.disconnect();
    timeInQueueDomObserver.disconnect();
}

$(document).ready(function () {
  // Function 1: Assign Priorities
  function assignChatPriority(arrayParent) {
     //Assign Priorities
     //Observe if time change, if change re-assign priority to dom node
     timeInQueueDomObserver.observe(
     $(incomingChat).find(".time_cell")[0],
     configtimeInQueue
  }

  // Function 2: Reorder DOM
  function orderIncomingChats() {
    //Reorder DOM save DOM elements to Array
    //Replace original DOM with new sorted DOM 
  }


  //Obervers Configuration
  let configChatsContainer = {
    childList: true,
  };
  let configtimeInQueue = {
    childList: true,
  };
  if (goSortDom) {
    //boolean is true go ahead run functions and observe
    assignChatPriority(incomingChatsRows);
    orderIncomingChats();
    incomingChatsDomObserver.observe(
      incomingChatsContainer[0],
      configChatsContainer
    );
  } else {
    //disconnect observers: WON'T WORK
    incomingChatsDomObserver.disconnect();
    timeInQueueDomObserver.disconnect();
  }
}

  1. 版本。 MutationObserver 断开连接:
$(document).ready(function () {
  // Function 1: Assign Priorities
  function assignChatPriority(arrayParent) {
     //Assign Priorities
     //Observe if time change, if change re-assign priority to dom node
     timeInQueueDomObserver.observe(
     $(incomingChat).find(".time_cell")[0],
     configtimeInQueue
  }

  // Function 2: Reorder DOM
  function orderIncomingChats() {
    //Reorder DOM save DOM elements to Array
    //Replace original DOM with new sorted DOM 
  }

  //Declaring DOM Observers for Time in Queue and DOM container dynamics
  var incomingChatsDomObserver = new MutationObserver(function (mutations) {
    mutations.forEach(function (mutation) {
      if (mutation.addedNodes.length) {
        for (let i = 0; i < mutation.addedNodes.length; i++) {
          if (
            mutation.addedNodes[i].attributes["data-priority"] === undefined
          ) {
            runExtensionFunctions();
          }
        }
      }
    });
    // ANSWERER: Now the observer disconnects itself after the run. Remember: MutationObserver's disconnect itself from *everywhere*
    incomingChatsDomObserver.disconnect();
  });
  var timeInQueueDomObserver = new MutationObserver(function (mutations) {
    mutations.forEach(function (mutation) {
      if (
        mutation.addedNodes.length === 1 &&
        mutation.addedNodes[0].nodeType === Node.TEXT_NODE &&
        mutation.removedNodes.length === 1 &&
        mutation.removedNodes[0].nodeType === Node.TEXT_NODE
      ) {
        runExtensionFunctions();
      }
    });
    // ANSWERER: Now the observer disconnects itself after the run. Remember: MutationObserver's disconnect itself from *everywhere*
    timeInQueueDomObserver.disconnect();
  });

  //Obervers Configuration
  let configChatsContainer = {
    childList: true,
  };
  let configtimeInQueue = {
    childList: true,
  };
  if (goSortDom) {
    //boolean is true go ahead run functions and observe
    assignChatPriority(incomingChatsRows);
    orderIncomingChats();
    incomingChatsDomObserver.observe(
      incomingChatsContainer[0],
      configChatsContainer
    );
  } else {
    //disconnect observers: WON'T WORK
    incomingChatsDomObserver.disconnect();
    timeInQueueDomObserver.disconnect();
  }
}

或者,看看下面的内容。 MutationObserver 绑定到按钮对象,因此单击按钮总是引用一次初始化的 MutationObserver。这样他们就可以断开连接并重新连接(尝试在浏览器中更改 div#changes):

<html>
<body>
    <button id="somebutton">bla</button>
    <div id="changes"></div>
    <script>
        document.querySelector("#somebutton").addEventListener("click", function () {
            if (!this.incomingChatsDomObserver) {
                this.incomingChatsDomObserver = new MutationObserver(function (mutations) {
                    console.log("incomingChatsDomObserver", mutations);
                });
            }

            if (!this.timeInQueueDomObserver) {
                this.timeInQueueDomObserver = new MutationObserver(function (mutations) {
                    console.log("timeInQueueDomObserver", mutations);
                });
            }

            if (this.observing) {
                this.observing = false;
                this.incomingChatsDomObserver.disconnect();
                this.timeInQueueDomObserver.disconnect();
                this.innerText = "inactive";
            } else {
                this.observing = true;
                const changingDiv = document.querySelector("#changes");
                this.incomingChatsDomObserver.observe(changingDiv, { attributes: true });
                this.timeInQueueDomObserver.observe(changingDiv, { attributes: true });
                this.innerText = "active";
            }
        });
    </script>
</body>
</html>