“return false”之所以被误用如此之多,是因为它看起来已经完成了我们赋予它的工作。浏览器不会将我们重定向到href中的链接,表单也不会继续提交。但是这有什么错呢?
可能你刚开始学习jQuery事件处理的时候,看到的第一个例子是关于如何防止浏览器执行默认行为,比如下面这段演示click事件的代码:复制代码如下:$ (a.toggle )。单击(function () {$ (# mydiv )。切换();返回false//阻止浏览器访问`#` });这个函数使用toggle来显示或隐藏#mydiv,然后阻止浏览器继续访问href中指定的链接。
类似上面的例子会让用户养成用“return false”来阻止浏览器执行默认行为的坏习惯。在本文中,我将讨论关于防止浏览器执行默认行为的两个非常重要的主题:
?选择正确的方法:
返回false或preventDefault、stopPropagation或stop immediate program?选择合适的位置,开始,结束,还是中间某个地方:
应该在事件回调的哪个部分取消浏览器的默认行为?注意:
当我在本文中提到事件冒泡时,我想表达的是,大多数事件都是先在初始DOM上触发,然后通过DOM树向上,在每一级父元素上触发。事件不会在同级节点或子节点上冒泡(当事件冒泡时,我们称之为事件捕获)。你可以在这里了解更多关于事件冒泡和捕获的信息。选择正确的方法
“return false”之所以被误用如此之多,是因为它看起来已经完成了我们赋予它的工作。浏览器不会再将我们重定向到href中的链接,表单也不会继续提交。但是这有什么错呢?
”return false“到底做了什么?
每次调用“return false”时,它实际上做了3件事:
event . prevent default();event . stop propagation();停止回调函数执行并立即返回。“等等”,你哭了!我只想让浏览器停止执行默认行为。我不需要它来做另外两件事。
在这3件事中,只有preventDefault用于阻止浏览器继续执行默认行为。除非你想阻止事件冒泡,否则使用return false会给你的代码埋下很大的隐患。让我们通过一个真实的例子来看看这种误用的后果:
这是我们用来演示的HTML:复制代码代码如下:div class= post h2a href= 3358 JB 51 . net my page/a/H2 div class= content teacher text./Div/Div class= post h2a href= 3358 JB 51 . net 我的另一页/a/h2div class= content 教师文本./div/div现在假设我们要在用户点击一篇文章的标题时,将文章动态加载到div.contentd:复制代码如下:jquery (document)。ready(function($){ $( div . post h2a )。Click (function () {var a=$ (this),href=a.attr (href ),//让jQuery正常化 href ,content=a.parent()。next();content . load(href # content );返回false//取消关注链接的默认行为});});这段代码工作得很好(至少目前是这样),但是如果我们继续沿着这条思路,并且如果我想在用户单击div.post元素(或它的任何子元素)时向它添加一个活动类,我需要向div.post添加一个
click回调:
复制代码,如下所示://inside document Ready:var posts=$( div。posts.click(function () { //从所有div.post帖子中移除active . Remove class( active );//加回这个一个$(这个)。add class(“active”);});现在,如果我们点击一篇文章的标题,这段代码会起作用吗?答案是否定的,因为我们在标题的点击回调中使用了return false而不是本该使用的,“return false”等于event . prevent default();add event . stop propagation();所以事件气泡被终止,click事件不会在div.post上冒泡,我们为它添加的事件回调当然也不会被调用。如果我们将它与现场或委派事件混合,情况会更糟。如下复制代码:$ (a )。click(function(){//dosomethingreturn false;});
$(a )。live(click ,function () { //这个不会火});那么我们真正需要的是什么?
preventDefault()
大多数情况下,使用return false时,真正需要的是e.preventDefault()。要使用e.preventDefault,需要确保将事件参数传递给回调函数(在本例中,就是那个e):复制代码代码如下:$ (a )。click(function(e){//e==our event data e . prevent default();});它将为我们完成所有工作,但不会阻止父节点继续处理事件。请记住,您在代码中设置的限制越少,您的代码就越灵活,也越容易维护。
stopPropagation()
但是在某些情况下,您可能需要停止事件冒泡。我们来看看下面的例子:复制代码代码如下:div class= post 普通文本然后a href= 3358jb51.net 链接/a然后更多文本。/div现在我们假设,如果你点击了A链接以外的div,我们希望发生一些事情(比如改变背景什么的),但是不能影响用户点击A链接的行为(从可用性的角度来说,这个例子不太好,你可能不希望用户点击别的地方发生什么)。复制代码如下:$ (div.post )。click(function(){//做第一件事;});
$(div.post a )。click(function (e) { //不要取消浏览器的默认动作//不要泡这个事件!e .停止传播();});在这种情况下,如果我们使用return false,将不会触发div的click事件,但是用户不会到达他们单击的链接。
stopImmediatePropagation()
这个方法将停止一个事件并继续执行。即使其他处理函数绑定到当前对象,所有绑定到对象的事件都将按绑定顺序执行。看一下下面的例子:复制代码如下:$ (div a )。单击(function(){//do something });
$(div a )。click(function (e) { //做点别的e . stop immediate propagation();});
$(div a )。单击(function(){//THIS NEVER FIRES });
$(div )。单击(function(){//THIS NEVER FIRES });你可能会觉得这个例子看起来很尴尬。是的,即便如此,有时确实会发生。如果你的代码非常复杂,不同的小部件和插件可能会向同一个对象添加事件。如果出现这种情况,您有必要了解并使用stopImmediatePropagation。
return false
只有当您同时需要preventDefault和stopPropagation,并且您的代码可以接受在回调完成之前不停止浏览器的默认行为时,才可以使用“return false”。但是我强烈建议你不要在写给其他jQuery开发者的演示代码中使用这种方法,因为这样会导致更多的误用,只有在确定有必要的时候才使用“return false”。
选择适当的位置
如果使用“return false”,只会在你的回调函数完成时取消浏览器的默认行为。但是,通过使用e.preventDefault,我们有了更多的选择,它可以随时阻止浏览器执行默认动作,不管你把它放在函数的哪个部分。
1. 开发阶段,
你应该总是把它放在第一行。你最不想做的事情可能是,当你在调试,把一个表单改成ajax提交的时候,它已经按照老方法提交了。2. 产品阶段,
如果采用渐进式增强,放在回调的末尾,或者逻辑的末尾。如果在普通页面上采用渐进式增强,那么在浏览器不支持JS(或者被禁用)的情况下,需要考虑服务器端对链接的click事件和表单的submit事件的处理。这里的好处是不考虑关闭js的情况,只考虑支持JS时的疯狂。如果你的回调代码错误抛出异常,我们来看看下面的代码:复制代码如下:var data={ };$(a )。单击(function(e){ e . prevent default();//取消默认行为//引发错误,因为“my”未定义$(“body”)。append(data . my . link);//原来的链接不起作用,而且‘酷’//JavaScript已经坏了。用户一无所有!});现在我们来看看同一个事件的效果,把preventDefault调用放在最下面:复制代码code如下:var data={ };$(a )。click(function (e) { //抛出错误,因为 my 未定义$(body )。append(data . my . link);//永远不会到达这一行,您的网站//会退回到使用 href 而不是这个//很酷的不完整JavaScript!e . prevent default();//取消默认行为});这也适用于表单提交。你可以更好地处理错误。不要期望你的代码一直正常工作。当错误发生时,最好有一个正确的响应,而不是假设代码不会出错。
3.在产品阶段,
如果函数是JS设计的,也要放在第一行。记住,不一定是函数的第一行,但是越快越好。这里的原则是:如果功能是通过JS实现的(不涉及服务器端交互),就不需要考虑兼容性。在这种情况下,在第一行添加可以防止#字符出现在URL中,但显然,您仍然应该添加尽可能多的错误处理代码,以防止用户在出错时不知所措。
结论
我希望本文传达的信息足以让您在需要阻止浏览器执行默认行为时做出正确的选择。记住,只有当你真正明白自己在做什么的时候,才使用“return false”,并确保在函数的正确位置调用相应的代码。最后,尽量保持代码的灵活性,尽量不要再使用“return false”了!