javascript - 添加元素时如何更改动态页面上的 DOM?
问题描述
我有一个网页,我正在尝试编写一个 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);
})();
我尝试了以下方法:
addEventListener("DOMNodeInserted", ...)
在将每个元素插入 DOM 时直接运行代码;但是,由于创建了无限循环,这导致了调用堆栈超出错误setInterval(...)
定期运行代码,寻找需要代码处理的元素;但是,这会导致部分处理或丢失数据,因为随着响应的进入,DOM 会发生变化,这是不规则的。addEventListener
→setTimeout
(如上面的代码所示)——这也不起作用。
我是否以错误的方式解决这个问题/是否有更简单的方法来处理这个问题?
解决方案
不推荐使用DomNodeInserted 等突变事件。
请改用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>
推荐阅读
- c - 如何在 cJSON 中测试布尔值是否为真/假
- python-3.x - 使用帮助功能后如何在mac终端返回ipython
- ruby-on-rails - 如果 Ruby 支持开放类,为什么 Rails 项目中的类会被同名的 Gem 类覆盖?
- ios - 将 xcode 更新到 9.4 后,react native ios build 失败。错误是“NSInteger”类型的值
- heroku - Heroku 中的 CLI 编辑器?
- sockets - 如何区分套接字句柄和文件句柄
- sql - SQL 查询以从不同日期的值中提取大约 90 天的值
- python - 唯一的 .txt 文件扩展名
- css - Webpack 没有拾取一些 CSS 文件
- ruby - 使用 Nokogiri 检索 XML 命名空间