HTML

7 阅读2分钟

script标签中defer和async的区别

如果页面顶部有一个庞大的脚本,它会“阻塞页面”。在下载并运行之前,用户无法看到页面内容

<p>...content before script...</p>

<script src="https://javascript.info/article/script-async-defer/long.js?speed=1"></script>

<!-- 以下在脚本加载完之前是不可见的 -->
<p>...content after script...</p>

defer

defer属性告诉浏览器不要等待脚本,继续构建DOM,脚本在“后台”加载,等到DOM构建完成后再运行。

<p>...content before script...</p>

<script defer src="https://javascript.info/article/script-async-defer/long.js?speed=1"></script>

<!-- 不等待脚本,立即显示 -->
<p>...content after script...</p>

defer永远不会阻塞页面,defer总是在DOM准备就绪时(但在DOMContentLoaded事件之前)执行。

<p>...content before scripts...</p>

<script>
  document.addEventListener('DOMContentLoaded', () => alert("DOM fully loaded and parsed after defer!"));
</script>

<script defer src="https://javascript.info/article/script-async-defer/long.js?speed=1"></script>

<p>...content after scripts...</p>


// 页面内容立即显示。
// DOMContentLoaded事件处理程序等待defer脚本执行完之后执行

defer脚本依然会保持相对顺序执行

async

async属性意味着该脚本是完全独立的

简单来说就是 async 脚本在后台加载完就立即运行

应用场景:将独立的第三方脚本集成到页面中时,比如计数器,广告等。

## 重绘 和 重排(回流)

重绘 (Redraw :某些元素的外观被改变所触发的浏览器行为; 例如:修改元素的填充颜色,会触发重绘;

重排 (Reflow :重新生成布局,重新排列元素(重新计算各节点和css具体的大小和位置:渲染树需要重新计算所有受影响的节点**);例如:改元素的宽高,会触发重排;

通过两者概念区别明显得知,重排要比重绘的成本大得多,我们应该尽量减少重排操作,减少页面性能消耗

优化

样式集中改变(减少重排次数):重写class

将 DOM 离线(减少重排次数):先display:none 再操作,完成后block

脱离文档流: 使用 absolute 或 fixed 脱离文档流(减小重排范围

善用内存:在内存中多次操作DOM,再整个添加到DOM树(减小重排范围) DIFF等