How to correctly use preventDefault(), stopPropagation(), or return false; on events
How to correctly use preventDefault(), stopPropagation(), or return false; on events
I’m sure this has been written about many times before and probably has hundreds of answers on StackOverflow.
Despite this we still find ourselves going through code bases and repeatedly finding the misuse (or interchangeable use, or combined use) of event.preventDefault()
, event.stopPropagation()
and return false;
.
So today we’re going to learn what the differences are between the three, and exactly how they function.
preventDefault()
, stopPropagation(),
and return false;
are not interchangeable, nor are they tools of trial-and-error.
We’ll start off with a pretty common UI pattern — a file upload panel — and see how each of them affect its behaviour.
https://github.com/FineUploader/fine-uploader
Image courtesy of FineUploader
https://fineuploader.com/demos.html
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,dropzone是button的父控件(之后的事件处理,涉及到事件冒泡)
Our HTML consists of three parts:
- An
input
to handle the file upload dialog. This is hidden (display: none;
) , as we will be triggering the upload dialog using the following two elements. - A
div
with the class offile-upload__dropzone
which acts as the main ‘drop zone’ where we will be able to drag-and-drop files (code not included) or click to open a file upload dialog. - An
a
tag with the class offile-upload__btn--upload
which will act as the “Upload files” button, which when clicked will open a file upload dialog.
html的页面效果如下
左边是drop files here,右边是Upload files的link
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代码,在页面加载的时候,不会调用函数,只是实例化函数。
然后拿到dropzone和button,然后给他们绑定上了click事件,并且click事件的handler都是fileUpload函数
Our JavaScript, like our HTML, also consists of three parts:
- A
fileUpload
function to trigger theclick
event on the file uploadinput
. - Assigning both the dropzone
div
anda
button to variables. - Adding event listeners to those, which when clicked invoke the
fileUpload
function.
If we were to try this out now, we may see some odd behaviour — after the first dialog has opened and we have chosen our file, a second one will open prompting us again. Keep reading and all will be revealed.
在FileUpload方法中打印event的currentTarget可以看出来,是谁触发了事件
function fileUpload(event) {
console.log(event.currentTarget);
document.querySelector('.file-upload__input').click();
}
event.preventDefault()
Prevents the browsers default behaviour (such as opening a link), but does not stop the event from bubbling up the DOM.
In our scenario, clicking on the “Upload files” button will invoke the fileUpload
function, as we would expect.
Being an a
tag, however, it also has a default behaviour — this being to navigate the browser to the location in the href
attribute. In this instance we have this set to #
, which in most browsers will just cause the page to jump back to the top.
Jumping back to the top of the page is not really our desired behaviour, so we can prevent this by using the preventDefault
method. This prevents the default behaviour of an element.
Modifying our JavaScript code, we can fix this so that clicking the link prevents the default behaviour of navigating to the location in the href
attribute, but still opens the file upload dialog.
dropzone.addEventListener('click', fileUpload); button.addEventListener('click', (event) => {
event.preventDefault();
fileUpload();
});
Here we have taken the click
event and prevented its default behaviour using event.preventDefault()
, then invoked the fileUpload()
function.
We still have the dialog box popping up twice, but hopefully the next section will solve this issue.
event.stopPropagation()
Prevents the event from bubbling up the DOM, but does not stop the browsers default behaviour.
For an in-depth explanation of event bubbling, I’d recommend this article about event propagation. https://www.sitepoint.com/event-bubbling-javascript/
But essentially, when an event is called on an element, that event bubbles up the DOM and gets called on all of the elements parents.
In our case, that means that when we click on the “File upload” button, that click
event is also called on all of its parent elements, including our dropzone.
To see this in action, we can remove the fileUpload()
call in the button event listener and the function will still be invoked when we click on the button because the click
event will bubble up the DOM and be called on the dropzone.
dropzone.addEventListener('click', fileUpload); button.addEventListener('click', event => event.preventDefault());
This bubbling is an example of event propagation, which is where the stopPropagation
method comes into play.
We can use it to prevent this default bubbling behaviour so that the event is only registered by the element it is called upon.
event propagation包括bubble和capture What is event bubbling and capturing?
dropzone.addEventListener('click', fileUpload); button.addEventListener('click', event => event.stopPropagation());
按照上面进行修改后,点击link,不会触发dropzone的click。只有点击dropzone,才会触发click
Now we see that not only does the click
event not bubble up the DOM, but by removing the preventDefault
method call the a
tag acts as it should again, by navigating to its href
attribute.
点击link后,会触发link本身的default behavior,点击link后,页面会跳转到一个新的url http://172.31.212.20:8082/FineUploaderTest/#,这个新的url后面带#
但是我们期待做以下三件事情
But this isn’t what we want. We wanted to call the fileUpload
function and also prevent the element’s default behaviour and prevent the event from bubbling up the DOM.
We could use both preventDefault
and stopPropagation
then call the fileUpload
function, like so.
dropzone.addEventListener('click', fileUpload); button.addEventListener('click', (event) => {
event.preventDefault();
event.stopPropagation();
fileUpload();
});
return false;
Usually seen in jQuery code, it Prevents the browsers default behaviour, Prevents the event from bubbling up the DOM, and immediately Returns from any callback.
In vanilla JavaScript, returning false
doesn’t have any effect on the default behaviour or event propagation of the element, as we can see here, it acts exactly as it did at the start.
dropzone.addEventListener('click', fileUpload); button.addEventListener('click', (event) => {
fileUpload();
return false;
});
It calls the click
event on the button, also navigating to it’s href
value, then bubbles up the DOM, calling the click
event on the dropzone too.
原生的js里面,return false没有意义。还是会navigate到href,然后事件冒泡到父控件,触发 父控件的click
However…
…in the context of jQuery, returning false
will immediately exit the event listeners callback. This has the effect of both:
- Preventing the default behaviour — navigating the browser to the
a
tag’shref
attribute. - Stopping any event propagation — stopping the
click
event from bubbling up the DOM.
If we refactor our code to jQuery, we can see this in practice.
const dropzone = $('.file-upload__drop-zone');
const button = $('.file-upload__btn--upload'); $(dropzone).on('click', fileUpload); $(button).on('click', (event) => {
fileUpload();
return false;
});
We call the fileUpload
method, then return false
to prevent any default behaviour or event propagation.
Conclusion
We should use these tools correctly and wisely.
Next time when we’re in this kind of situation, we shouldn’t just play around with event.preventDefault()
, event.stopPropagation()
and return false;
until we get the desired result.
We should think what it is we want to achieve, and how to get there — not through trial-and-error and luck — but through thinking through the problem and applying the correct solution.
How to correctly use preventDefault(), stopPropagation(), or return false; on events的更多相关文章
- e.preventDefault()和e.stopPropagation()以及return false的作用和区别
前段时间开发中,遇到一个父元素和子元素都有事件时,发现会出现事件冒泡现象,虽然知道ev.stopPropagation()和ev.preventDefault()其中一个是阻止事件冒泡和阻止默认行为, ...
- JS preventDefault ,stopPropagation ,return false
所谓的事件有两种:监听事件和浏览器对特殊标签元素的默认行为事件.监听事件:在节点上被监听的事件操作,如 select节点的change事件,a节点的click事件.浏览器的默认事件:特定页面元素上带的 ...
- js 阻止事件冒泡和默认行为 preventDefault、stopPropagation、return false
preventDefault: preventDefault它是事件对象(Event)的一个方法,作用是取消一个目标元素的默认行为.既然是说默认行为,当然是元素必须有默认行为才能被取消,如果元素本身就 ...
- preventDefault()、stopPropagation()、return false 之间的区别
“return false”之所以被误用的如此厉害,是因为它看起来像是完成了我们交给它的工作,浏览器不会再将我们重定向到href中的链接,表单也不会被继续提交,但这么做到底有什么不对呢? 可能在你刚开 ...
- preventDefault()、stopPropagation()、return false 的区别
preventDefault() e.preventDefault()阻止浏览器默认事件 stopPropagation() e.stopPropagation()阻止冒泡 return false ...
- 阻止事件冒泡两种方式:event.stopPropagation();和return false;
jQuery提供了两种方式来阻止事件冒泡. 方式一:event.stopPropagation(); $("#div1").mousedown(function (event) { ...
- e.preventDefault() e.stopPropagation()和return false的区别
e.preventDefault(); //阻止事件的默认行为,比如a标签的转向,但不阻止事件的冒泡传播e.stopPropagation() //阻止事件的冒泡传播,但不阻止其默认行为returne ...
- preventDefault, stopPropagation, return false -JS事件处理中的坑
我们以一个文件上传ui重设计为例子来探讨这几个函数的区别: 其中的html代码如下: <div class="file-upload"> <input type= ...
- 【转】stopPropagation, preventDefault 和 return false 的区别
因为有父, 子节点同在, 因为有监听事件和浏览器默认动作之分. 使用 JavaScript 时为了达到预期效果经常需要阻止事件和动作执行. 一般我们会用到三种方法, 分别是 stopPropagat ...
随机推荐
- L2Dwidget.js L2D网页动画人物添加
hexo 添加live2d看板动画 https://www.jianshu.com/p/3a6342e16e57 首先贴出官网代码 官网地址配置:https://www.npmjs.com/packa ...
- 本人亲测-C#常用工具类
/* * HTTP接口工具类 */ public class HttpUitls { /* * get请求 */ public static string Get(string Url) { //Sy ...
- DedeAMPZ配置php的curl扩展
DedeAMPZ配置php的curl扩展 curl是一个利用URL语法在命令行方式下工作的文件传输工具.它支持很多协议:FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, ...
- nginx服务学习第二章
nginx.config文件中字符串不显示高亮 nginx服务搭建完成后,查看nginx.config的时候发现没有高亮字符,要想配置文件出现高亮方便观看,需要修改一些配置文件,修改步骤如下: # m ...
- 服务器挂载 ntfs32 硬盘
1,fdisk -l 查看硬盘名称 2,mount -t ntfs-3g /硬盘名/ /目标目录/ 3,umount /硬盘名/ 4,如果卸载不了 就fuser -km /目标目录/
- ERP人员组织岗位权限菜单关系视图
- PowerDesigner 生成SQL Server 注释脚本
--生成数据表的注释EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=[%R%?[N]]%.q:COMMENT% , @l ...
- js 代码位置不同,导致随着点击函数执行次数累加
每个人书写代码的习惯都不同吃,思想也都不一样,但在工作中为了减少工作量与时间,难免遇到要用别人写的代码.这次在使用同事的代码中,偶然发现的问题,因为js不好,所以一眼也没发现问题所在,查了查网上才知道 ...
- 2017 网易游戏互娱游戏研发4.21(offer)
网易游戏互娱(offer) 去年这个时候就参加过网易游戏的实习生招聘,到今年总共收到了4次拒信.不过这次运气好,终于get了最想要的offer.去年实习生互娱笔试挂,秋招笔试挂,今年春招互娱投了连笔试 ...
- 【leetcode】1234. Replace the Substring for Balanced String
题目如下: You are given a string containing only 4 kinds of characters 'Q', 'W', 'E' and 'R'. A string i ...