【问题标题】:MutationObserver script for Tampermonkey works in Firefox, but not in ChromeTampermonkey 的 MutationObserver 脚本在 Firefox 中有效,但在 Chrome 中无效
【发布时间】:2023-01-25 04:29:16
【问题描述】:

这是保存元素出现时的状态的脚本(saveMessage 函数),然后使用 MutationObserver 监视元素的 className 的变化并恢复它的保存状态(resetMessage 函数)。实际上它一直在 Firefox 中工作,直到最近的一个补丁(我相信是 v.104),并且在过去的一年里没有在 Chrome 中工作(带有 className 'chat-line__message--deleted-notice' 的元素的文本赢了'被恢复,只是没有任何反应)。现在它在 FF 中似乎什么都不做,但因为它在 FF 中工作而不是同时在 Chrome 中工作,我认为它一定与标准或类似的东西有一些非常小的偏差。任何想法有什么问题吗?

// ==UserScript==
// @name         Twitch: <message deleted>
// @namespace    https://greasyfork.org/users/221926
// @version      1.3
// @description  show deleted messages in twitch chat
// @match      https://www.twitch.tv/*
// @grant        none
// @run-at       document-end
// ==/UserScript==

(function () {
  'use strict'

  function saveMessage (el) {
    if (el.initialChildNodes) return
    el.initialChildNodes = Array.from(el.childNodes)
  }

  function resetMessage (el) {
    while (el.initialChildNodes == null) { el = el.parentNode }
    while (el.lastChild) { el.removeChild(el.lastChild) }
    el.initialChildNodes.forEach(childNode => el.appendChild(childNode))
    el = el.closest('.chat-line__message')
    el.style.backgroundColor = 'rgba(255, 0, 0, .1)'
    el.style.boxShadow = 'inset 4px 0 0 0 rgba(255, 0, 0, .4)'
  }

  new MutationObserver(mutationList => {
    mutationList.forEach(mutation => {
      Array.from(mutation.addedNodes).forEach(el => {
        switch (el.className) {
          case 'chat-line__message': saveMessage(el.querySelector('.chat-line__username-container').parentNode); break
          case 'chat-line__message--deleted-notice': resetMessage(el); break
        }
      })
    })
  }).observe(document.body, { childList: true, subtree: true, characterData: true })
})()

【问题讨论】:

  • 站点通常根据浏览器提供不同的内容。使用devtools设置断点或者添加console.log调试。

标签: javascript tampermonkey mutation-observers


【解决方案1】:

看起来 Twitch 现在替换了整个 .chat-line__message 节点,因此您不能再将初始状态保存在节点本身中。但是,有一个解决方案:在这种情况下,替换元素意味着您会通过删除 chat-line__message 节点然后添加 chat-line__message 节点来获得突变。

下面的代码保存删除的节点,然后,当新的已删除的消息添加节点,在新节点之前恢复旧节点已删除的消息节点并删除该新节点。

设置 node.isrestored 可以防止循环,因为我们的代码也会触发 MutationObserver。

(function () {
  'use strict'
  var previousMutationRemoved;

  function resetMessage (el) {
    if (previousMutationRemoved == null) return;
    previousMutationRemoved.style.backgroundColor = 'rgba(255, 0, 0, .1)';
    previousMutationRemoved.style.boxShadow = 'inset 4px 0 0 0 rgba(255, 0, 0, .4)';
    previousMutationRemoved.isrestored = 'true';
    el.parentNode.insertBefore(previousMutationRemoved.cloneNode(true), el);
    previousMutationRemoved = null;
    el.isrestored = 'true';
    el.parentNode.removeChild(el);
  }

  new MutationObserver(mutationList => {
    mutationList.forEach(mutation => {
      Array.from(mutation.removedNodes).forEach(node => {
        if (node.nodeType == Node.ELEMENT_NODE) {
          if (node.className == 'chat-line__message' && node.isrestored != 'true') {
            previousMutationRemoved = node;
          }
        }
      });
      Array.from(mutation.addedNodes).forEach(node => {
        if (node.nodeType == Node.ELEMENT_NODE) {
          if (node.className == 'chat-line__message' && node.isrestored != 'true') {
            if(node.querySelector(".chat-line__message--deleted-notice")) {
              resetMessage(node);
            }
          }
        }
      })
    });
    previousMutationRemoved = null;
  }).observe(document.body, { childList: true, subtree: true, characterData: true })
})()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-23
    • 2016-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-19
    相关资源
    最近更新 更多