当浏览器解析HTML文档时,它会自上而下地逐行读取和解析代码。当遇到JavaScript(内联或外链)时,浏览器会根据脚本的加载方式(同步或异步)来决定如何处理。
-
同步加载:默认情况下,浏览器会暂停HTML解析以及CSS渲染,并立即下载和执行JavaScript代码。执行完毕后,继续解析HTML。这种方式会影响页面的加载速度。在
<script>
标签中添加defer
属性可以使脚本异步加载。 -
defer:表示脚本应该延迟执行。设置defer属性的脚本会在页面所有元素解析完成后才执行,并且如果有多个带有defer属性的脚本,它们会按照在文档中出现的顺序依次执行。这对于需要操作DOM但不希望阻塞页面解析的脚本非常有用。
-
当HTML解析过程中遇到带有defer属性的标签,浏览器会继续解析HTML,构建DOM树,而不会等待脚本下载和执行。脚本会在后台下载,等到DOM完全构建完成后才会执行。因此,使用defer属性可以避免在脚本下载和执行期间中断HTML解析,从而提升页面加载和渲染的效率。
-
async:表示脚本应该异步加载。设置async属性的脚本会在下载的同时继续解析HTML页面,一旦脚本下载完成,会立即执行,不会阻塞页面的其他内容加载。这对于那些不依赖页面DOM结构和其他脚本的独立脚本非常有用
同步加载与异步加载的区别总结
特性 | 同步加载(默认) | 异步加载(async / defer ) |
---|---|---|
加载行为 | 阻塞 HTML 解析和渲染,直到脚本下载并执行完毕 | 不阻塞 HTML 解析和渲染,脚本下载与页面解析并行进行 |
执行时机 | 下载完成后立即执行 | async :下载完成后立即执行defer :HTML 解析完成后按顺序执行 |
执行顺序 | 按照 <script> 标签在 HTML 中的顺序依次执行 |
async :取决于下载完成的顺序defer :按照 <script> 标签的顺序 |
适用场景 | 适用于需要严格顺序执行且不介意阻塞页面加载的脚本 | 适用于独立于其他脚本、不依赖 DOM 或其他脚本的独立脚本 |
性能影响 | 可能导致页面加载缓慢,用户体验差 | 提升页面加载速度,改善用户体验 |
常见事件类型
- 鼠标事件:
click
、mouseover
、contextmenu
(右键菜单) - 键盘事件:
keydown
、keypress
、keyup
,可通过event.keyCode
判断按键 - 表单事件:
submit
(表单提交)、change
(输入内容改变) - 窗口事件:
load
(页面加载)、resize
(窗口大小变化)
事件流模型
事件流分为三个阶段:
- 捕获阶段:事件从
window
逐级向下传递到目标元素 - 目标阶段:事件到达目标元素。
- 冒泡阶段:事件从目标元素逐级向上传递到
window
三种 DOM 事件绑定方式
1. 内联事件处理器(Inline Event Handlers)
描述:直接在 HTML 元素的属性中定义事件处理代码。
优点:
- 简单直观,适合快速原型开发或小型项目。
缺点:
- 将 HTML 结构与 JavaScript 代码耦合,不利于维护和扩展。
- 不利于复用事件处理逻辑。
- 安全性较低,容易引发 XSS 攻击。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>内联事件处理器示例</title>
</head>
<body>
<button onclick="