一个bug引发的思考

2,086 阅读1分钟

在项目中,我定义了一个fn函数,每次onresize事件触发的时候,都要执行fn

<div id="root"></div>
<script>
    function fn() {
      document.write("<style>html{font-size:16px}</style>");
      const root = document.getElementById("root") 
    }
    fn()
    window.onresize = fn
</script>

当首次加载页面时,是正常显示:body元素中含有style标签,并设置了字体大小,而当resize事件触发的时候,此时,获取通过document.getElementById("root")获取元素显示null,页面DOM结构如下:

image.png

body中的元素不见了!!!并且style标签中的元素放到head中了.调整代码。当直接在页面上直接删除body标签

<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>

  <script>
    function fn() {
      document.write("<style>html{font-size:16px}</style>");
      const root = document.getElementById("root");
    }
    fn();
    window.onresize = fn;
 </script>

渲染后的层级结构和上上面效果一样,说明当body标签不存在时,创建的style标签被谷歌浏览器放到head中了

image.png

document.write

mdn解释是这样的: 因为 document.write 需要向文档中写入内容,所以,若在一个已关闭(例如,已完成加载)的文档上调用 document.write,就会自动调用 document.open这将清空该文档的内容 

而document.open:

  • 此时已注册到文档、文档中的节点或文档的window的所有事件监听器会被清除。
  • 文档中的所有节点会被清除

根据以上信息,onload完成之后调用document.write,自动调用了document.open,会将文档中的body节点删除掉,goole在将document.write创建的style元素放到head中,此时id为root元素已经访问不到了