仅使用 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 以供可能需要它的其他人使用:
之前的一些说明:

  1. 正如我之前提到的,CargoCollective 允许通过 HTML 编辑选项添加内部 js 脚本(代码必须插入脚本标签之间)。
  2. 由于设计者要求我删除了“---”占位符(在我原来的问题中),因此解决方案不包括它。
  3. 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>