JavaScript 如何检测元素何时添加到 DOM?

前端开发 Jul 7, 2022

JavaScript 如何检测元素何时添加到 Dom?这在 Web 网页中,尤其是针对不能操控源码的网站,是极为常见的问题。那么如何有效检测元素已成功渲染呢,本文旨在对此问题进行探讨。

需求背景

清风明月阁 ,是基于 Wiki.js 搭建的 Web 应用;其内容默认的排版(UI )并不是很喜欢;而 赫蹏 (专为中文网页内容设计的排版样式增强。它基于通行的中文排版规范,可为网站的读者带来更好的内容阅读体验)这种风格,令我更觉得舒服。于是就想为 清风明月阁 接入下 赫hè蹏tí

如何使用赫蹏?

项目地址: https://github.com/sivan/heti ,其使用方法如下:

  1. 在页面的 </head> 标签前中引入 heti.css 样式文件:

    <link rel="stylesheet" href="//unpkg.com/heti/umd/heti.min.css">
    
  2. 在要作用的容器元素上增加 class="heti" 的类名即可:

    <article class="entry heti">
      <h1>我的世界观</h1>
      <p>有钱人的生活就是这么朴实无华,且枯燥。</p>
      ……
    </article>
    

备注:赫蹏是正文区域的样式增强,不是_normalize.css_或_CSS Reset_的替代。因此不建议将它作用在根标签(如 <body><div class="container">)上。

Wiki.jsGhost 一样,有强大的后台,支持插入 Css / JS 代码于 head 或 body;那问题就来了,何时为文章内容加 heti 这个类呢?

JavaScript 如何检测元素何时添加到 Dom?

当然,可以很容易想到以下方案:

window.onload = () => {}

setTimeout(function(){}, 100)

但是,这两种方案,可以有效,但不够干净,不能得知元素是否已被渲染的准确时机。截至 2018 年,您应该使用 MutationObserver 来检测元素何时添加到 DOM。现在,所有现代浏览器(Chrome 26+、Firefox 14+、IE11、Edge、Opera 15+ 等)都广泛支持 MutationObservers。此外,将元素添加到 DOM 后,您将能够检索其实际尺寸。于是乎,为 清风明月阁 添加「赫蹏」,其体验就能变得非常自然,没有中间不符合预期的变化。

<link rel="stylesheet" href="//unpkg.com/heti/umd/heti.min.css">
<script type="text/javascript">
  window.addEventListener('DOMContentLoaded', (event) => {
    var observer = new MutationObserver(function(mutations) {
      var contents = document.querySelector('.contents')
      if (document.contains(contents)) {
        contents.classList.add('heti', 'heti--classic');
        observer.disconnect();
      }
    });
    observer.observe(document, {attributes: false, childList: true, characterData: false, subtree:true});
  }); 
</script>

另外,值得一提的是,在此处使用了 DOMContentLoaded 事件(当初始 HTML 文档完全加载和解析时触发,无需等待样式表、图像和子框架完成加载),在其成功回调中,再调用 MutationObservers,算是细微处优化处理。

清风明月阁 | 赫蹏

本文首发于:JavaScript 如何检测元素何时添加到 DOM? | 悠然宜想亭

您可能感兴趣的文章

Tags

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.