仅使用 DOMContentLoaded 后如何 DOM 更改页面内容
How to DOM changed page content after only using DOMContentLoaded
我正在开发基于 cargocollective 的系统并尝试使用 javascript 更改现有项目标签。现在,当用户输入地址时,标签会在 1 或 2 秒内从一个阶段转换到另一个阶段,因此用户首先看到:
然后几秒钟后看到:
有没有办法修改它,以便用户在页面加载完成后看不到更改?
这是我当前的代码:
<script>
document.addEventListener('DOMContentLoaded', (event) => {
window.setTimeout(() => {
let titles = document.querySelectorAll(".thumbnails .title span");
let titlesArray = Array.from(titles);
let tArray = [titlesArray.length];
titlesArray.forEach(el => {
let titleSplit =[];
titleSplit = el.textContent.split('---');
for (let i = 0; i < tArray.length; i++)
{
el.textContent = "";
for (let j = 0; j < titleSplit.length; j++)
{
el.innerHTML += `${titleSplit[j]}</br>`;
}
}
});
}, 400);
});
</script>
有几点需要说明:
1. 系统只允许内部js脚本,不允许HTML编辑,也就是只允许插入脚本标签之间的代码
2. 解决方案必须在 javascript 以备将来使用。
3.“---”仅供装饰使用,将替换为 SVG 图片。
4.脚本标签位置在文件中间。另外,脚本和页面末尾之间有很多内容。
5. 查看源代码:webpage in context
不要等待 DOMContentLoaded
,也不要将功能放入 setTimeout
。相反,将 <script>
放在脚本依赖的最后一个元素之后 - 最后一个 .thumbnails .title span
:
<div class="thumbnails">
<div class="title">
<span>
...
</span>
</div>
</div>
<script>
// Put the code here
</script>
这样,更改应该会立即发生,甚至在页面呈现给用户之前,这样他们第一次看到它时就会看起来像他们想要的那样。
关于代码,let tArray = [titlesArray.length];
没有多大意义 - 您正在创建一个包含单个元素的数组,一个数字,您继续在嵌套循环中对其进行迭代。如果你只是想用空行替换 ---
s,并且 span 只包含纯文本,那么使用:
for (const span of document.querySelectorAll(".thumbnails .title span")) {
span.innerHTML = span.innerHTML.split('---').join('<br><br>');
}
<div class="thumbnails">
<div class="title">
<span>
foobar
---
barbaz
</span>
</div>
</div>
<script>
for (const span of document.querySelectorAll(".thumbnails .title span")) {
span.innerHTML = span.innerHTML.split('---').join('<br><br>');
}
</script>
(你需要两个 <br>
才能在两个单词之间有两个换行符,以便在呈现的输出中出现一个空行)
如果你不能改变<script>
标签的位置,和脚本和[=52=结尾之间有很多内容], 和 脚本 运行 在你需要的元素存在之前,那么当脚本 [=56] 时你将无法立即 select 这些元素=]s,也不能等待 DOMContentLoaded 存在,因为从出现所需元素到完全解析 DOM 可能需要很长时间。唯一的选择是将 MutationObserver 附加到文档,它可以 运行 在插入新节点时进行回调。如果一个新节点是您要更改的节点之一,请更改它。这可确保在渲染之前尽快发生更改:
<script>
new MutationObserver((mutations) => {
for (const mutation of mutations) {
for (const node of mutation.addedNodes) {
if (node.nodeType === 1 && node.matches('.thumbnails .title span')) {
node.innerHTML = node.innerHTML.split('---').join('<br><br>');
}
}
}
})
.observe(document.body, { childList: true, subtree: true });
</script>
<div class="thumbnails">
<div class="title">
<span>
foobar
---
barbaz
</span>
</div>
<div class="title">
<span>
foobar
---
barbaz
</span>
</div>
</div>
它可以变得更便宜 - 例如,只有在所有 thumbnails
的容器存在时才附加深度观察者,并在容器结束后取消附加它 - 但有关 [=53 的更多信息=] 需要结构。
我已经设法解决了我的问题,并决定在此处 post 以供可能需要它的其他人使用:
之前的一些说明:
- 正如我之前提到的,CargoCollective 允许通过 HTML 编辑选项添加内部 js 脚本(代码必须插入脚本标签之间)。
- 由于设计者要求我删除了“---”占位符(在我原来的问题中),因此解决方案不包括它。
- CargoCollective 的文档中没有提到具体的辅助函数
'thumbnails_render_complete'
,我是在聊天会话中从他们的支持那里得到的。
希望对大家有所帮助
<script>
Cargo.Event.on('thumbnails_render_complete', function(pid) {
let titles = document.querySelectorAll(".thumbnails .title span");
let titlesArray = Array.from(titles);
let tArray = titlesArray.length;
titlesArray.forEach(el => {
let titleSplit =[];
titleSplit = el.textContent.split('-');
for (let i = 0; i < tArray; i++) {
el.textContent = "";
for (let j = 0; j < titleSplit.length; j++) {
if ( j === 0 ) {
el.innerHTML += `${titleSplit[j]}</br>`;
}
else {
let subtext = titleSplit[j];
el.innerHTML += `${subtext}</br>`;
}
}
}
});
});
</script>
我正在开发基于 cargocollective 的系统并尝试使用 javascript 更改现有项目标签。现在,当用户输入地址时,标签会在 1 或 2 秒内从一个阶段转换到另一个阶段,因此用户首先看到:
然后几秒钟后看到:
有没有办法修改它,以便用户在页面加载完成后看不到更改?
这是我当前的代码:
<script>
document.addEventListener('DOMContentLoaded', (event) => {
window.setTimeout(() => {
let titles = document.querySelectorAll(".thumbnails .title span");
let titlesArray = Array.from(titles);
let tArray = [titlesArray.length];
titlesArray.forEach(el => {
let titleSplit =[];
titleSplit = el.textContent.split('---');
for (let i = 0; i < tArray.length; i++)
{
el.textContent = "";
for (let j = 0; j < titleSplit.length; j++)
{
el.innerHTML += `${titleSplit[j]}</br>`;
}
}
});
}, 400);
});
</script>
有几点需要说明:
1. 系统只允许内部js脚本,不允许HTML编辑,也就是只允许插入脚本标签之间的代码
2. 解决方案必须在 javascript 以备将来使用。
3.“---”仅供装饰使用,将替换为 SVG 图片。
4.脚本标签位置在文件中间。另外,脚本和页面末尾之间有很多内容。
5. 查看源代码:webpage in context
不要等待 DOMContentLoaded
,也不要将功能放入 setTimeout
。相反,将 <script>
放在脚本依赖的最后一个元素之后 - 最后一个 .thumbnails .title span
:
<div class="thumbnails">
<div class="title">
<span>
...
</span>
</div>
</div>
<script>
// Put the code here
</script>
这样,更改应该会立即发生,甚至在页面呈现给用户之前,这样他们第一次看到它时就会看起来像他们想要的那样。
关于代码,let tArray = [titlesArray.length];
没有多大意义 - 您正在创建一个包含单个元素的数组,一个数字,您继续在嵌套循环中对其进行迭代。如果你只是想用空行替换 ---
s,并且 span 只包含纯文本,那么使用:
for (const span of document.querySelectorAll(".thumbnails .title span")) {
span.innerHTML = span.innerHTML.split('---').join('<br><br>');
}
<div class="thumbnails">
<div class="title">
<span>
foobar
---
barbaz
</span>
</div>
</div>
<script>
for (const span of document.querySelectorAll(".thumbnails .title span")) {
span.innerHTML = span.innerHTML.split('---').join('<br><br>');
}
</script>
(你需要两个 <br>
才能在两个单词之间有两个换行符,以便在呈现的输出中出现一个空行)
如果你不能改变<script>
标签的位置,和脚本和[=52=结尾之间有很多内容], 和 脚本 运行 在你需要的元素存在之前,那么当脚本 [=56] 时你将无法立即 select 这些元素=]s,也不能等待 DOMContentLoaded 存在,因为从出现所需元素到完全解析 DOM 可能需要很长时间。唯一的选择是将 MutationObserver 附加到文档,它可以 运行 在插入新节点时进行回调。如果一个新节点是您要更改的节点之一,请更改它。这可确保在渲染之前尽快发生更改:
<script>
new MutationObserver((mutations) => {
for (const mutation of mutations) {
for (const node of mutation.addedNodes) {
if (node.nodeType === 1 && node.matches('.thumbnails .title span')) {
node.innerHTML = node.innerHTML.split('---').join('<br><br>');
}
}
}
})
.observe(document.body, { childList: true, subtree: true });
</script>
<div class="thumbnails">
<div class="title">
<span>
foobar
---
barbaz
</span>
</div>
<div class="title">
<span>
foobar
---
barbaz
</span>
</div>
</div>
它可以变得更便宜 - 例如,只有在所有 thumbnails
的容器存在时才附加深度观察者,并在容器结束后取消附加它 - 但有关 [=53 的更多信息=] 需要结构。
我已经设法解决了我的问题,并决定在此处 post 以供可能需要它的其他人使用:
之前的一些说明:
- 正如我之前提到的,CargoCollective 允许通过 HTML 编辑选项添加内部 js 脚本(代码必须插入脚本标签之间)。
- 由于设计者要求我删除了“---”占位符(在我原来的问题中),因此解决方案不包括它。
- CargoCollective 的文档中没有提到具体的辅助函数
'thumbnails_render_complete'
,我是在聊天会话中从他们的支持那里得到的。
希望对大家有所帮助
<script>
Cargo.Event.on('thumbnails_render_complete', function(pid) {
let titles = document.querySelectorAll(".thumbnails .title span");
let titlesArray = Array.from(titles);
let tArray = titlesArray.length;
titlesArray.forEach(el => {
let titleSplit =[];
titleSplit = el.textContent.split('-');
for (let i = 0; i < tArray; i++) {
el.textContent = "";
for (let j = 0; j < titleSplit.length; j++) {
if ( j === 0 ) {
el.innerHTML += `${titleSplit[j]}</br>`;
}
else {
let subtext = titleSplit[j];
el.innerHTML += `${subtext}</br>`;
}
}
}
});
});
</script>