摘要
很多同学对阻止事件冒泡和阻止事件默认行为容易混淆, 项目中因为一些原因也需要阻止浏览器的一些默认行为, 这里就简单总结一下.
阻止事件冒泡
什么是事件冒泡这里就不再赘述了, 网上的文章一大把, 这里就简述一下如何阻止事件冒泡, 阻止事件冒泡在使用浏览器原生 API 的情况下, 是需要分情况考虑的, 毕竟有个个性的浏览器 IE, 这里分为 IE 实现和 W3C 标准实现.
在 W3C 标准实现中, 我们阻止事件冒泡可以很容易使用标准 API
基本语法:
event.stopPropagation();
IE 实现下 (这里主要指 IE 低版本 IE9 以下版本, 因为 IE9 也实现了 W3C 标准)
基本语法:
event.cancelBubble = bool;
当然 IE 标准并不是只有 IE 支持, 其实很多浏览器都实现了 cancelBubble 支持, 但是后来虽然浏览器没有取消对 cancelBubble 属性的支持, 设置了之后也会无效, 所以建议的兼容语法是:
- function eventCallback(e){
- e = e||Windows.event;
- if(e.stopPropagation){ // 通过浏览器能力进行兼容性检测
- e.stopPropagation();
- }else if(e.cancelBubble){
- e.cancelBubble = true;
- }
- }
当然说到阻止事件冒泡这个问题, 也要简单提一下 event.stopPropagation 和 event.stopImmediatePropagation 的异同点:
相同点是两者都能阻止标准事件注册方式注册的事件 (addEventListener,IE 是 attachEvent) 向父级节点继续冒泡
不同点从名字上可以看出, Immediate 立即的意思, event.stopImmediatePropagation 不止能阻止往父级节点冒泡, 还能阻止当前节点其它事件的继续执行 (比如往一个元素上注册了多个事件, 那么在第一个事件执行的时候, 通过调用 event.stopImmediatePropagation, 会阻止其它事件的执行)
上面代码需要注意的一点是, IE 下 e 不存在, 从 Windows 中获取, 简单做了兼容处理. 可以尝试使用 return false
阻止浏览器默认行为
在开始之前, 首先需要了解什么是浏览器的默认行为, 我这里简单举几个例子:
点击 a 标签, 如果设置了 href 会执行跳转
点击输入框, 输入框会获取焦点
点击右键, 会弹出浏览器右键菜单
点击 submit, 会提交其所在表单
点击 checkbox 会选中或者反选
还有其他的很多, 这里就不一一列举了
同样的对于阻止浏览器默认行为的实现也分为 W3C 标准实现和 IE 实现 (这里也只是指 IE9 以下的实现)
在 W3C 标准实现中, 其基本语法如下:
event.preventDefault();
在 IE 实现中, 其基本语法如下:
Windows.event.returnValue = false;
所以其兼容版本伪代码如下
- function eventCallback(e){
- e = e || Windows.event;
- if(e.preventDefault){
- e.preventDefault()
- }else {
- e.returnValue = false;
- }
- }
这里简单那 checkbox 做一个小的 demo:
- <!DOCTYPE>
- <html>
- <head>
- <title>preventDefault Demo</title>
- </head>
- <body>
- <h1>Please click on the checkbox</h1>
- <form>
- <label for="chk_just_for_test">Checkbox:</label>
- <input type="checkbox" id="chk_just_for_test"/>
- </form>
- <script>
- let chk = document.querySelector('#chk_just_for_test');
- chk.addEventListener('click',e=>{
- console.log('sorry ,do not let you check this checkbox');
- e.preventDefault(); // 这里不考虑 IE 低版本兼容性问题
- })
- </script>
- </body>
- </HTML>
有兴趣的其它场景都可以写个小 demo 玩玩.
同样 W3C 标准实现中, 我们可以通过 event.defaultPrevented 来确定 event.preventDefault 方法是否被调用, 基本模式如下:
- if (e.defaultPrevented) {
- /* the default was prevented */
- }
当然不是所有的事件都可以被 cancel,浏览器也提供了 cancelable 属性来判断事件是否可以被取消, 如果 cancelable 为 false, 那么便无法阻止浏览器的默认行为, 如果在一个不可撤销的事件上调用 preventDefault, 会抛出错误, 所以建议在调用之前判断事件是否可被取消.
下面是一个来自于 mdn 的例子, 有兴趣的可以直接看原文
浏览器厂商提议滚轮事件只有第一次可被取消
- function preventScrollWheel(event) {
- if (typeof event.cancelable !== 'boolean' || event.cancelable) {
- // The event can be canceled, so we do so.
- event.preventDefault();
- } else {
- // The event cannot be canceled, so it is not safe
- // to call preventDefault() on it.
- console.warn(`The following event couldn't be canceled:`);
- console.dir(event);
- }
- }
- document.addEventListener('wheel', preventCancelableEvents);
- # 总结
阻止默认冒泡和阻止浏览器默认行为需要关注的是兼容性问题, 其它内容大家只需要关注 mdn, 已经很详细的列出了兼容问题,对前端 & node 有兴趣的欢迎微信交流, 如果你能看到弹框弹出微信二维码的话.
附录
每个 API 的浏览器兼容情况如下:
event.stopPropagation
event.stopImmediatePropagation
Windows.event.returnValue
event.preventDefault
event.cancelable
event.cancelBubble
来源: https://www.cnblogs.com/Johnzhang/p/10183494.html