我们以一个文件上传ui重设计为例子来探讨这几个函数的区别:

其中的html代码如下:

<div class="file-upload">
<input type="file" name="upload-file" class="file-upload__input" style="display: none;" /> <div class="file-upload__drop-zone">
<span class="file-upload__drop-zone-text">Drop files here</span>
<a href="#" class="file-upload__btn--upload">Upload files</a>
</div>
</div>

HTML包含有三部分内容:

1. 一个inpyout空间来处理文件上传的对话.在这里,我们设置为hidden,因为我们并不想使用浏览器默认给出的控件;

2. 一个class为file-upload__dropzone的div元素,它作为主要的"drop zone"拖拽区,如果有代码支持的话,可以直接拖拽文件到这个区域。

3. 一个a元素,它具有file-upload__btn--upload作为其css类,它作为实际的"upload files"按钮,当我们点击它时,就能够打开文件选择对话框

Javascript部分:

function fileUpload() {
document.querySelector('.file-upload__input').click();
} const dropzone = document.querySelector('.file-upload__drop-zone');
const button = document.querySelector('.file-upload__btn--upload'); dropzone.addEventListener('click', fileUpload);
button.addEventListener('click', fileUpload);

js也有三部分组成:

1. 一个fileUpload函数用于触发input元素的click事件

2.div和a元素获取并赋予变量

3.给这几个元素添加事件侦听,当click时就调用fileUpload函数以模拟触发file input的点击

如果我们直接实验,我们会发现很多诡异的行为:当第一个对话框打开并选择文件后,又有第二个会打开

event.preventDefault()

该函数用于阻止浏览器的默认行为(比如当我们点击a标签的时候,自然就打开a中的链接,这个行为就是默认的行为),但是并不会阻止事件的bubbling,也就是说其父亲元素依然会接受到对应该元素的事件

在我们的例子中,当我们点击upload files按钮时,就会调用fileUpload函数,这和我们的预期时一致的。

而作为a标签,其默认行为是引导浏览器nav到href所指定的url中,在这里,我们设置为#,大多数浏览器解释为跳到页面的top处。

而跳转到页面的top处可能并不是我们希望的行为,因此,我们可以通过使用preventDefault方法来阻止这个行为。

通过修改我们的js代码,我们可以阻止a标签的默认行为,但是依然会调用fileUpload函数:

dropzone.addEventListener('click', fileUpload);

button.addEventListener('click', (event) => {
event.preventDefault();
fileUpload();
});

这时,虽然点击a标签不再跳转到页面top处,但是文件对话框依然会弹出两次。。。

需要注意的是:

1.preventDefault有继承性,如果在父亲元素的事件处理函数中调用了event.preventDefault,那么子元素对应的event默认行为也将丢失

2.如果希望在子组件中要覆盖这个行为,我们可以通过在子组件的event handler中最后执行 return true; 来恢复!

调试evenyout.preventDefault

有的时候,浏览器的行为非常奇怪,往往就是因为在某些组件上调用过preventDefault函数,而我们又无法知晓是哪个元素身上调用的,这时需要调试。

一个比较好的聪敏的办法是使用类似proxy代理wrapper将event的该函数重新包装:

var oldEPD = Event.prototype.preventDefault;
Event.prototype.preventDefault = function() {
debugger;
oldEPD.call(this);
};

这样的话就会在有该调用时代码停止供我们查找

event.stopPropagation()

这个函数可以阻止发生在子元素上的事件继续向上冒泡,但是不会阻止浏览器的默认行为.

上面的例子中,由于我们点击a元素后,a元素的click handler中会触发对话框,而随后a的click事件继续bubble到上级元素,也就是dropzone,而该dropzone元素也有监听click事件因此就又会被调用fileUpload,这就是为什么文件对话框弹出两次的原因。我们可以通过stopPropagation来阻止事件继续网上冒泡。

我们来看终级解决方案:

dropzone.addEventListener('click', fileUpload);

button.addEventListener('click', (event) => {
event.preventDefault();
event.stopPropagation();
fileUpload();
});

return false

通常return false这个代码仅仅在jQuery的事件处理函数中有效,对于原生的js代码并无任何影响。

而在jquery的代码中return false又有两个效果:

1. preventDefault

2. stopPropagation

const dropzone = $('.file-upload__drop-zone');
const button = $('.file-upload__btn--upload'); $(dropzone).on('click', fileUpload); $(button).on('click', (event) => {
fileUpload();
return false;
});

preventDefault, stopPropagation, return false -JS事件处理中的坑的更多相关文章

  1. event.stopPropagation()、event.preventDefault()与return false的区别

    做小demo时经常用到return false来取消默认事件,但一直不是很懂它和preventDefault()等的区别,今天查了查文档和大神们的博客,在这里对相关知识点做一个总结 首先开门见山,总结 ...

  2. 【转】stopPropagation, preventDefault 和 return false 的区别

    因为有父, 子节点同在, 因为有监听事件和浏览器默认动作之分. 使用 JavaScript 时为了达到预期效果经常需要阻止事件和动作执行. 一般我们会用到三种方法, 分别是  stopPropagat ...

  3. stopPropagation, preventDefault 和 return false 的区别

    因为有父, 子节点同在, 因为有监听事件和浏览器默认动作之分. 使用 JavaScript 时为了达到预期效果经常需要阻止事件和动作执行. 一般我们会用到三种方法, 分别是 stopPropagati ...

  4. stopPropagation, preventDefault 和 return false

    e.stopPropagation()此方法用于阻止事件冒泡或者事件捕获.IE8及以下中没有此方法,使用e.cancelBubble=false 来阻止事件冒泡. 当标准W3C中,事件包括捕获阶段和冒 ...

  5. event.stopPropagation(),event.preventDefault()和return false的区别

    event.stopPropagation(),event.preventDefault()和return false的区别 1.event.stopPropagation()方法 这是阻止事件的冒泡 ...

  6. event.preventDefault() vs. return false

    使用jquery方式的话,以下是等效的 return false === event.stopPropagation + event.preventDefault() //1. event.preve ...

  7. js的stopPropagation()、cancelBubble、preventDefault()、return false的分析

    个人笔记,如有错误,望指出. 事件冒泡,举个列子: <li> <a href='http://www.baidu.com'>点击a</a> </li> ...

  8. JS 之 阻止事件冒泡,阻止默认事件,event.stopPropagation()和event.preventDefault(),return false的区别

    在前端开发中,有时我们需要阻止冒泡和阻止默认事件的发生. 一.event.stopPropagation() 阻止事件的冒泡,不让事件向documen上蔓延,但是默认事件任然会执行,当调用这个方法的时 ...

  9. 阻止事件冒泡,阻止默认事件,event.stopPropagation()和event.preventDefault(),return false的区别

    1.event.stopPropagation()方法 这是阻止事件的冒泡方法,不让事件向documen上蔓延,但是默认事件任然会执行,当你掉用这个方法的时候,如果点击一个连接,这个连接仍然会被打开, ...

随机推荐

  1. js 替换字符串中的双引号

    text.replace(/\"/g, ''); 可根据此方法去掉字符串中的双引号

  2. ucoreOS_lab7 实验报告

    所有的实验报告将会在 Github 同步更新,更多内容请移步至Github:https://github.com/AngelKitty/review_the_national_post-graduat ...

  3. python async

    理解 python 的 async:1. 协程后面的技术也是 IO 多路复用, Nginx 和 nodejs 都充分利用了这种机制. 2. Flask 线程中为什么不能直接使用标准库 asyncio ...

  4. HBase安装学习

    一.下载安装 $ wget http://archive.cloudera.com/cdh5/cdh/5/hbase-1.2.0-cdh5.7.0.tar.gz $ tar -zxvf hbase-1 ...

  5. 网络爬虫之使用pyppeteer替代selenium完美绕过webdriver检测

    1引言 曾经使用模拟浏览器操作(selenium + webdriver)来写爬虫,但是稍微有点反爬的网站都会对selenium和webdriver进行识别,网站只需要在前端js添加一下判断脚本,很容 ...

  6. liteos 异常接管(十五)

    1 概述 1.1 基本概念 异常接管是操作系统对在运行期间发生异常的情况进行处理的一系列动作,譬如打印异常发生时当前函数调用栈信息. cpu现场信息.任务的堆栈情况等. 异常接管作为一种调测手段,可以 ...

  7. Asp.Net Core 开发之旅之.net core 连接数据库

    数据库连接字符串放入配置文件中 打开appsettings.json 添加ConnectionStrings 例子如下: { "Logging": { "IncludeS ...

  8. 渗透测试学习 十九、 XSS跨站脚本漏洞详解 续2

    二阶注入环境搭建 74cms 3.4 直接将源码放在PHPstudy的www路径下,在地址栏中输入127.0.0.1回车 然后进入网站首页,在填写简历里面存在二阶注入 先注册一个账号 创建简历 前面的 ...

  9. Ubuntu 18.04安装 pyenv、pyenv-virtualenv、virtualenv、Numpy、SciPy、Pillow、Matplotlib

    1.目前Python版本管理工具有很多,pyenv是比较好用的一款,安装如下: 输入: git clone https://github.com/pyenv/pyenv.git ~/.pyenv ec ...

  10. 使用 IDEA 翻译插件

    使用 IDEA 翻译插件 1.安装 在IDEA插件中搜索 translation根据下载量排序有个完全匹配名称的插件,下载,重启 2.配置翻译插件 都是中文,就不说了