淺析return false的正確使用
可能在你剛開始學習關(guān)于jQuery事件處理時,看到的第一個例子就是關(guān)于如何阻止瀏覽器執(zhí)行默認行為,比如下面這段演示click事件的代碼:
$("a.toggle").click(function () {
$("#mydiv").toggle();
return false; // Prevent browser from visiting `#`
});
這個函數(shù)使用toggle來顯示或者隱藏#mydiv,然后阻止瀏覽器繼續(xù)訪問href中指定的鏈接。
像上面這樣的例子會讓用戶養(yǎng)成使用“return false”來阻止瀏覽器執(zhí)行默認行為的壞習慣,在這篇文章里,我將會討論關(guān)于阻止瀏覽器執(zhí)行默認行為的兩個非常重要的主題:
•選擇正確的方法: return false還是preventDefault,stopPropagation或者stopImmediatePropagation
•選擇合適的位置,開始,結(jié)束,還是中間某個地方:你應(yīng)該在事件回調(diào)的哪個部分取消瀏覽器執(zhí)行默認行為?
注意:當我在這篇文章中提到event bubbling(事件冒泡),我想表達的是大部分事件都是先在初始DOM上觸發(fā),然后再通過DOM樹往上,在每一級父元素上觸發(fā),事件不會在兄弟節(jié)點或是子節(jié)點上冒泡(當事件向下冒泡時,我們叫它事件捕捉(event capturing)),你可以在這里了解更多關(guān)于事件起泡和捕捉的介紹。
選擇正確的方法
“return false”之所以被誤用的如此厲害,是因為它看起來像是完成了我們交給它的工作,瀏覽器不會再將我們重定向到href中的鏈接,表單也不會被繼續(xù)提交,但這么做到底有什么不對呢?
”return false“到底做了什么?
當你每次調(diào)用”return false“的時候,它實際上做了3件事情:
•event.preventDefault();
•event.stopPropagation();
•停止回調(diào)函數(shù)執(zhí)行并立即返回。
“等等”,你叫了起來!我只是想讓瀏覽器停止繼續(xù)執(zhí)行默認行為而已,我不需要它去做另外2件事。
這3件事中用來阻止瀏覽器繼續(xù)執(zhí)行默認行為的只有preventDefault,除非你想要停止事件冒泡,否則使用return false會為你的代碼埋下很大的隱患,讓我們通過一個真實的例子來看看這樣的誤用會造成什么后果:
這是我們用來演示的HTML:
<div class="post">
<h2><a >My Page</a></h2>
<div class="content">
Teaser text...
</div>
</div>
<div class="post">
<h2><a >My Other Page</a></h2>
<div class="content">
Teaser text...
</div>
</div>
現(xiàn)在假設(shè)我們想要在用戶點擊文章標題時,將文章動態(tài)載入到div.contentd中:
jQuery(document).ready(function ($) {
$("div.post h2 a").click(function () {
var a = $(this),
href = a.attr('href'), // Let jQuery normalize `href`,
content = a.parent().next();
content.load(href + " #content");
return false; // "cancel" the default behavior of following the link
});
});
這段代碼可以正常工作(至少目前是),但如果我們順著這個思路繼續(xù),如果我想要在用戶點擊了一個div.post元素(或者任何一個它的子元素)時,給它加上一個active類,我就需要給div.post增加了一個click回調(diào):
// Inside Document Ready:
var posts = $("div.post");
posts.click(function () {
// Remove active from all div.post
posts.removeClass("active");
// Add it back to this one
$(this).addClass("active");
});
現(xiàn)在,如果我們點擊一個帖子的標題,這段代碼會工作嗎?答案是不會,因為我們在標題的click回調(diào)里使用了return false而不是我們應(yīng)該使用的,”return false“等于event.preventDefault();加event.stopPropagation();,所以事件冒泡就被終止了,click事件不會被冒泡到div.post上,我們?yōu)樗砑拥氖录卣{(diào)當然也就不會被調(diào)用了。
如果我們把它和live或者delegate事件混在一起使用時,情況就更糟了。
$("a").click(function () {
// do something
return false;
});
$("a").live("click", function () {
// THIS WON'T FIRE
});
那么我們真正需要的是什么呢?
preventDefault()
大多數(shù)情況下,當你使用return false時,你其實真正需要的是e.preventDefault()。要使用e.preventDefault,你需要確保你傳遞了event參數(shù)到你的回掉函數(shù)中(在這個例子里,就是那個e):
$("a").click(function (e) {
// e == our event data
e.preventDefault();
});
它會替我們完成所有工作,但不會阻止父節(jié)點繼續(xù)處理事件,要記住,你放在代碼中的限制越少,你的代碼就越靈活,也就越易于維護。
stopPropagation()
但有些情況下,你有可能需要停止事件冒泡,讓我們看看下面的例子:
<div class="post">
Normal text and then a <a >link</a> and then more text.
</div>
現(xiàn)在,讓我們假設(shè)如果你點了div上除了a鏈接之外的地方,我們希望能發(fā)生點什么事情(比如改變下背景什么的),但是不能影響用戶點擊a鏈接的行為(從可用性的角度,這個例子不怎么好,你可能不希望用戶點擊別的地方時發(fā)生任何事情)。
$("div.post").click(function () {
// Do the first thing;
});
$("div.post a").click(function (e) {
// Don't cancel the browser's default action
// and don't bubble this event!
e.stopPropagation();
});
在這種情況下,如果我們使用return false,div的click事件不會被觸發(fā),但是用戶也不會到達他們點的那個鏈接。
stopImmediatePropagation()
這個方法會停止一個事件繼續(xù)執(zhí)行,即使當前的對象上還綁定了其它處理函數(shù),所有綁定在一個對象上的事件會按綁定順序執(zhí)行,看看下面的例子:
$("div a").click(function () {
// Do something
});
$("div a").click(function (e) {
// Do something else
e.stopImmediatePropagation();
});
$("div a").click(function () {
// THIS NEVER FIRES
});
$("div").click(function () {
// THIS NEVER FIRES
});
你可能會覺得這個例子看起來很別扭,沒錯,盡管如此,但有時這的確會發(fā)生,如果你的代碼非常復(fù)雜,那么不同的widgets和plugin就有可能在同一個對象上添加事件,如果遇到這種情況,那你就很有必要理解和使用stopImmediatePropagation。
return false
只有當你同時需要preventDefault和stopPropagation,并且你的代碼可以接受直到你的回調(diào)執(zhí)行完成才停止執(zhí)行瀏覽器的默認行為,那你就可以使用”return false“。但我強烈建議你別在寫給其它jQuery開發(fā)者的演示代碼中使用這個方法,因為這會造成更多誤用,只有在你確信非用不可的情況下再去使用”return false“。
選擇適當?shù)奈恢?/STRONG>
如果你使用了”return false“,它只會在你的回調(diào)函數(shù)執(zhí)行結(jié)束才去取消瀏覽器的默認行為,但是使用e.preventDefault,我們有更多的選擇,它可以隨時停止瀏覽器執(zhí)行默認動作,而不管你將它放在函數(shù)的哪個部分。
1. 開發(fā)階段,你應(yīng)該總是將它放在第一行。你最不想做的事情可能就是你正在調(diào)試將一個form改成ajax提交的時候,它卻已經(jīng)被按照老方法提交了。
2. 產(chǎn)品階段,如果你采用了漸進增強(progressive enhancement),那就把它放到回調(diào)的結(jié)束位置,或者是邏輯終點,如果在一個普通頁面采用漸進增強,那你就需要在服務(wù)器端考慮如果瀏覽器不支持JS時(或者被禁用時),對鏈接的click事件和表單的提交事件的處理。這里的好處是,我們不考慮關(guān)閉JS的情況,只考慮支持js時的強狂,如果你的回調(diào)代碼出錯拋出了異常,讓我們看看下面的代碼:
var data = {};
$("a").click(function (e) {
e.preventDefault(); // cancel default behavior
// Throws an error because `my` is undefined
$("body").append(data.my.link);
// The original link doesn't work AND the "cool"
// JavaScript has broken. The user is left with NOTHING!
});
現(xiàn)在,讓我們看看同樣的事件,把preventDefault調(diào)用放在底部的效果:
>
var data = {};
$("a").click(function (e) {
// Throws an error because `my` is undefined
$("body").append(data.my.link);
// This line is never reached, and your website
// falls back to using the `href` instead of this
// "cool" broken JavaScript!
e.preventDefault(); // cancel default behavior
});
這對表單提交也同樣有效,你可以更好的應(yīng)對出錯的情況,別指望你的代碼一直正常工作,在發(fā)生錯誤時有正確的應(yīng)對總勝過假設(shè)代碼不會出錯。
3.在產(chǎn)品階段,如果功能這設(shè)計JS,那就還應(yīng)該放在第一行。
記住,不必非得是函數(shù)的第一行,但是越早越好,這里的原則是:如果函數(shù)的功能是通過JS實現(xiàn)的(不涉及服務(wù)端交互),那就沒必要考慮兼容,在這種情況下,添加在第一行可以防止URL中出現(xiàn)#字符,但顯然,你還是應(yīng)該盡可能多的增加些錯誤處理代碼,以防止用戶在出錯時變得不知所措。
結(jié)論
我希望這篇文章傳達的信息足夠你在需要阻止瀏覽器執(zhí)行默認行為時做出正確的選擇。記住,只有當你真的明白你在做什么時,才使用”return false“,并確保你是在函數(shù)的正確位置調(diào)用了相應(yīng)的代碼。最后,盡可能保持代碼的靈活性,盡量不要再用“return false”了!
- 學習jQuey中的return false
- javascript中return,return true,return false三者的用法及區(qū)別
- Jquery的each里用return true或false代替break或continue
- js中return false(阻止)的用法
- 淺析onsubmit校驗表單時利用ajax的return false無效問題
- JavaScript中return false的用法
- 基于jquery實現(xiàn)智能提示控件intellSeach.js
- jQuery.each使用詳解
- JavaScript中的數(shù)組遍歷forEach()與map()方法以及兼容寫法介紹
- JS中的forEach、$.each、map方法推薦
- 詳解JavaScript中的forEach()方法的使用
- JavaScript使用forEach()與jQuery使用each遍歷數(shù)組時return false 的區(qū)別
相關(guān)文章
對Layer彈窗使用及返回數(shù)據(jù)接收的實例詳解
今天小編就為大家分享一篇對Layer彈窗使用及返回數(shù)據(jù)接收的實例詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-09-09詳解ant-design-pro使用qiankun微服務(wù)
這篇文章主要介紹了ant-design-pro使用qiankun微服務(wù)詳解,其實微服務(wù)需要有主應(yīng)用和子應(yīng)用,?一個子應(yīng)用可以配置多個相關(guān)聯(lián)的主應(yīng)用,配置方法都是一樣的,對ant-design-pro微服務(wù)配置相關(guān)知識,感興趣的朋友一起看看吧2022-03-03理解JAVASCRIPT中hasOwnProperty()的作用
JavaScript中hasOwnProperty函數(shù)方法是返回一個布爾值,指出一個對象是否具有指定名稱的屬性2013-06-06