事件之HTML5事件

一  定义

DOM 规范并未涵盖浏览器都支持的所有事件。很多浏览器根据特定的用户需求或使用场景实现了 自定义事件。HTML5 详尽地列出了浏览器支持的所有事件

二 事件

1、contextmenu 事件

  • 定义:以专门用于表示何时该显示上下文菜单,从而允许开发者取消默认的上下文菜单并提供自定义菜单
  • 事件冒泡:只要给 document 指定一个事件处理程序就可以处理页面上的所有同类事件。事件目标是触发操作的元素。
  • 事件取消
    • 在 DOM 合规的浏览器中使用 event.preventDefault()
    • 在 IE8 及更早版本中将 event.returnValue 设置为 false
// contextmenu 事件应该算一种鼠标事件,因此 event 对象上的很多属性都与光标位置有关。通常,自定义的上下文菜单都是通过 oncontextmenu 事件处理程序触发显示,并通过 onclick 事件处理程序触发隐藏的。来看下面的例子:
<!DOCTYPE html> 
<html> 
<head> 
 <title>ContextMenu Event Example</title> 
</head> 
<body> 
 <div id="myDiv">Right click or Ctrl+click me to get a custom context menu. 
 Click anywhere else to get the default context menu.</div> 
 <ul id="myMenu" style="position:absolute;visibility:hidden;background-color: 
 silver"> 
 <li><a href="http://www.somewhere.com"> somewhere</a></li> 
 <li><a href="http://www.wrox.com">Wrox site</a></li> 
 <li><a href="http://www.somewhere-else.com">somewhere-else</a></li> 
 </ul> 
</body> 
</html> 

// 这个例子中的<div>元素有一个上下文菜单<ul>。作为上下文菜单,<ul>元素初始时是隐藏的。以下是实现上下文菜单功能的 JavaScript 代码:
window.addEventListener("load", (event) => { 
 let div = document.getElementById("myDiv"); 
 div.addEventListener("contextmenu", (event) => { 
 event.preventDefault(); 
 let menu = document.getElementById("myMenu"); 
 menu.style.left = event.clientX + "px"; 
 menu.style.top = event.clientY + "px"; 
 menu.style.visibility = "visible"; 
 }); 
 document.addEventListener("click", (event) => { 
 document.getElementById("myMenu").style.visibility = "hidden"; 
 }); 
}); 

// 这里在<div>元素上指定了一个 oncontextmenu 事件处理程序。这个事件处理程序首先取消默认行,确保不会显示浏览器默认的上下文菜单。接着基于 event 对象的 clientX 和 clientY 属性把<ul>元素放到适当位置。最后一步通过将 visibility 属性设置为"visible"让自定义上下文菜单显示出来。另外,又给 document 添加了一个 onclick 事件处理程序,以便在单击事件发生时隐藏上下文菜单(系统上下文菜单就是这样隐藏的)。

2、beforeunload 事件

定义:会在 window 上触发,用意是给开发者提供阻止页面被卸载的机会。

  • 这个事件会在页面即将从浏览器中卸载时触发,如果页面需要继续使用,则可以不被卸载。
  • 这个事件不能取消, 否则就意味着可以把用户永久阻拦在一个页面上
  • 相反,这个事件会向用户显示一个确认框,其中的消息表明浏览器即将卸载页面,并请用户确认是希望关闭页面,还是继续留在页面上
// 需要将 event.returnValue 设置为要在确认框中显示的字符串,并将其作为函数值返回(对于 Safari 和 Chrome 来说),如下所示:
window.addEventListener("beforeunload", (event) => { 
 let message = "I'm really going to miss you if you go."; 
 event.returnValue = message; 
 return message; 
}); 

3、DOMContentLoaded 事件

  • 定义+运行时机:DOMContentLoaded 事件会在 DOM 树构建完成后立即触发,而不用等待图片、JavaScript 文件、CSS 文件或其他资源加载完成
事件区别
window 的 load 事件会在页面完全加载后触发,因为要等待很多外部资源加载完成,所以会花费较长时间
DOMContentLoaded 事件DOMContentLoaded 可以让开发者在外部资 源下载的同时就能指定事件处理程序,从而让用户能够更快地与页面交互
  • 事件处理:需要给 document 或 window 添加事件处理程序(实际的事件目标是 document,但会冒泡到 window)
// 一个在 document 上监听 DOMContentLoaded 事件的例子:
document.addEventListener("DOMContentLoaded", (event) => { 
 console.log("Content loaded"); 
});
  • 注意事项
    • DOMContentLoaded 事件的 event 对象中不包含任何额外信息(除了 target 等于 document)
    • DOMContentLoaded 事件通常用于添加事件处理程序或执行其他 DOM操作。这个事件始终在 load 事件之前触发
    • 对于不支持 DOMContentLoaded 事件的浏览器,可以使用超时为 0 的 setTimeout()函数,通过 其回调来设置事件处理程序,比如: setTimeout(() => { // 在这里添加事件处理程序 }, 0);
    • 以上代码本质上意味着在当前 JavaScript 进程执行完毕后立即执行这个回调。页面加载和构建期间, 只有一个 JavaScript 进程运行。所以可以在这个进程空闲后立即执行回调。

4、readystatechange 事件

定义:旨在提供文档或元素加载状态的信息

属性:支持 readystatechange 事件的每个对象都有一个 readyState 属性(字符串值)

  • uninitialized:对象存在并尚未初始化
  • loading:对象正在加载数据
  • loaded:对象已经加载完数据
  • interactive:对象可以交互,但尚未加载完成
  • complete:对象加载完成

使用场景:

  • 在 document 上使用时

值为"interactive"的 readyState 首先会触发 readystatechange 事件,时机类似于 DOMContentLoaded。进入交互阶段,意味着 DOM 树已加载完成,因而可以安全地交互了。此时图片和其他外部资源不一定都加载完了

// 使用 readystatechange 事件:
document.addEventListener("readystatechange", (event) => { 
 if (document.readyState == "interactive") { 
 console.log("Content loaded"); 
 } 
}); 
// 这个事件的 event 对象中没有任何额外的信息,连事件目标都不会设置。

  • 在与 load 事件共同使用时

这个事件的触发顺序不能保证。在包含特别多或较大外部资源的页面中,交互阶段会在 load 事件触发前先触发。而在包含较少且较小外部资源的页面中,这个 readystatechange 事件有可能在 load 事件触发后才触发

解决方案:实践中为了抢到较早的时机,需要同时检测交互阶段和完成阶段

document.addEventListener("readystatechange", (event) => { 
 if (document.readyState == "interactive" || 
 document.readyState == "complete") { 
 document.removeEventListener("readystatechange", arguments.callee); 
 console.log("Content loaded"); 
 } 
});

// 当 readystatechange 事件触发时,这段代码会检测 document.readyState 属性,以确定当前是不是交互或完成状态。如果是,则移除事件处理程序,以保证其他阶段不再执行。注意,因为这里的事件处理程序是匿名函数,所以使用了 arguments.callee 作为函数指针

5、pageshow 与 pagehide 事件

页面缓存:Firefox 和 Opera 开发了一个名为往返缓存(bfcache,back-forward cache)的功能,此功能旨在使用 浏览器“前进”和“后退”按钮时加快页面之间的切换。这个缓存不仅存储页面数据,也存储 DOM 和 JavaScript 状态,实际上是把整个页面都保存在内存里

pageshow事件:

  • 使用场景:其会在页面显示时触发,无论是否来自往返缓存。
  • 在新加载的页面上, pageshow 会在 load 事件之后触发
  • 在来自往返缓存的页面上,pageshow 会在页面状态完全恢复后触发
  • 注意,虽然这个事件的目标是 document,但事件处理程序必须添加到 window 上。
// 展示了追踪这些事件的代码:
(function() { 
 let showCount = 0; 
 window.addEventListener("load", () => { 
 console.log("Load fired"); 
 }); 
 window.addEventListener("pageshow", () => { 
 showCount++; 
 console.log(`Show has been fired ${showCount} times.`); 
 }); 
})(); 

// 这个例子使用了私有作用域来保证 showCount 变量不进入全局作用域。在页面首次加载时,showCount 的值为 0。之后每次触发 pageshow 事件,showCount 都会加 1 并输出消息。
// 如果从包含以上代码的页面跳走,然后又点击“后退”按钮返回以恢复它,就能够每次都看到 showCount 递增的值。这是因为变量的状态连同整个页面状态都保存在了内存中,导航回来后可以恢复。如果是点击了浏览器的“刷新”按钮,则 showCount 的值会重置为 0,因为页面会重新加载
  • 属性:persisted
    • 这个属性是一 个布尔值,如果页面存储在了往返缓存中就是 true,否则就是 false
// 在事件处理程序中检测这个属性:
(function() { 
 let showCount = 0; 
 window.addEventListener("load", () => { 
 console.log("Load fired"); 
 }); 
 window.addEventListener("pageshow", () => { 
 showCount++; 
 console.log(`Show has been fired ${showCount} times.`, 
 `Persisted? ${event.persisted}`); 
 }); 
})(); 

// 通过检测 persisted 属性可以根据页面是否取自往返缓存而决定是否采取不同的操作

pagehide事件:

  • 使用场景:这个事件会在页面从浏览器中卸载后,在 unload 事件之前触发。
    • 是在 document 上触发,但事件处理程序必须被添加到 window
    • event 对象中同样包含 persisted 属性
// 以下代码检测了event.persisted 属性:
window.addEventListener("pagehide", (event) => { 
 console.log("Hiding. Persisted? " + event.persisted); 
});

persisted属性对比为 true为false
pageshow 事件表示页面是从往返缓存中加载的第一次触发 pageshow 事件时 persisted 始终是 false
pagehide 事件表示页面在卸载之后会被保存在往返缓存中而第一次触发 pagehide 事件时 persisted 始终是 true(除非页面不符合使用往返缓存的条件)。

6、hashchange 事件

定义:用于在 URL 散列值(URL 最后#后面的部分)发生变化时通知开发者。这是因为开发者经常在 Ajax 应用程序中使用 URL 散列值存储状态信息或路由导航信息

使用:onhashchange 事件处理程序必须添加给 window,每次 URL 散列值发生变化时会调用它。event 对象有两个新属性:oldURL 和 newURL。这两个属性分别保存变化前后的 URL,而且是包含散列值的 完整 URL

// 下面的例子展示了如何获取变化前后的 URL:
window.addEventListener("hashchange", (event) => { 
 console.log(`Old URL: ${event.oldURL}, New URL: ${event.newURL}`); 
}); 

// 如果想确定当前的散列值,最好使用 location 对象:
window.addEventListener("hashchange", (event) => { 
 console.log(`Current hash: ${location.hash}`); 
});

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值