如何在添加元素时更改动态页面上的 DOM?

How to alter DOM on dynamic page as elements are added?

我有一个网页,我正在尝试为其编写一个 Tampermonkey 脚本,该脚本将在特定元素中找到虚拟终端 (VT) 颜色代码,然后用 <span> 元素替换它们。我相信核心代码可以正常工作,但问题是我如何有效地部署代码,以便在通过站点自己的代码将新元素添加到 DOM 时,我的代码将检测并重写。

(function() {
    'use strict';

    document.addEventListener("DOMNodeInserted",function(){
        setTimeout(function(){
        var vtRe = /\x5b(?<color>\d{2}(?:;1)?|0)m/;
        var nodeList = document.querySelectorAll("div.command-output:not(.vt-colorized)");
        nodeList.forEach((node) => {
            // Replace VT Color Codes with span colors
            var iText = node.innerText;
            var arr = iText.split(/\x1b/);
            node.innerText = '';
            arr.forEach((item) => {
                var newEle = document.createElement("span");
                let match = vtRe.exec(item);
                if (match) {
                    switch(match.groups.color) {
                        case "30":
                            newEle.style.color = 'black';
                            break;
                        case "31":
                            newEle.style.color = 'darkred';
                            break;
                        case "32":
                            newEle.style.color = 'darkgreen';
                            break;
                        case "33":
                            newEle.style.color = 'darkyellow';
                            break;
                        case "34":
                            newEle.style.color = 'darkblue';
                            break;
                        case "35":
                            newEle.style.color = 'darkmagenta';
                            break;
                        case "36":
                            newEle.style.color = 'darkcyan';
                            break;
                        case "37":
                            newEle.style.color = 'darkgray';
                            break;
                        case "30;1":
                            newEle.style.color = 'gray';
                            break;
                        case "31;1":
                            newEle.style.color = 'red';
                            break;
                        case "32;1":
                            newEle.style.color = 'green';
                            break;
                        case "33;1":
                            newEle.style.color = 'yellow';
                            break;
                        case "34;1":
                            newEle.style.color = 'blue';
                            break;
                        case "35;1":
                            newEle.style.color = 'magenta';
                            break;
                        case "36;1":
                            newEle.style.color = 'cyan';
                            break;
                        case "37;1":
                            newEle.style.color = 'white';
                            break;
                        case "32":
                            newEle.style.color = 'green';
                            break;
                        case "0":
                            break;
                        default:
                            break;
                    }
                }
                newEle.innerText = item.replace(vtRe,'');
                node.append(newEle);
            });
            node.classList.add('vt-colorized');
        });
    }, 10000);
    },false);
})();

我试过以下方法:

我是不是做错了way/is有没有更简单的方法来处理这个问题?

为避免无限循环,您可以在添加要在侦听器中检查的节点之前设置一个标志:

(function () {
    'use strict';
    let inserting = false;
    document.addEventListener("DOMNodeInserted", function () {
        if (inserting) return;
        inserting = true;
        var vtRe = /\x5b(?<color>\d{2}(?:;1)?|0)m/;
        // ...rest of your code
        inserting = false;
    });
})();

像 DomNodeInserted 这样的突变事件是 deprecated

改用 MutationObserver

简化示例:

const targetNode = document.querySelector("#cont");
const observerOptions = {
  childList: true,
  attributes: false,
  // Omit (or set to false) to observe only changes to the parent node
  subtree: true
}

const observer = new MutationObserver(callback);
observer.observe(targetNode, observerOptions);

function callback(mutationList, observer) {
  mutationList.forEach((mutation) => {
    if (mutation.type === 'childList' && mutation.addedNodes.length) {
      mutation.addedNodes.forEach(el => {
        if (el.matches('#cont ul li')) {
          console.log('<li> Added')
          el.style.color = 'red'
        }
      });
    }
  });
}

// insert an element every 1.5 seconds
let ctr=0;
const timer = setInterval(()=>{   
   if(++ctr===5){     
     clearInterval(timer)
   }
   const li = document.createElement('li')
   li.textContent = `Item ${ctr}`
   document.querySelector('#cont ul').append(li)
},1500)
  
<div id="cont">
  <ul>
  </ul>
</div>