當頁面有<form>操作時,瀏覽器會有默認的響應enter鍵就提交form表單。
看html代碼
<form action="http://www.7k7k.com"> <input type="text">
當你在input框里輸入后,按enter鍵,就會默認提交form,
但實際需求並不是這樣的,比如在input輸入時會有彈出的suggestion選項讓用戶選擇,用戶按了enter鍵后並不想直接提交,所以需要在部分邏輯下需要取消這種默認響應。
解決方法非常簡單,如下
document.onkeydown = function(e) { var e = e || event; if(e.keyCode == 13) { alert("自己的邏輯"); e.preventDefault ? e.preventDefault() : (e.returnValue = false); } }
這段代碼在ie下是通過了,
但在firefox,chrome下按enter鍵,先會alert("自己的邏輯"),再又接着執行默認的form提交,當時花了很多時間,一直以為是取消默認事件哪里寫錯了,后面不經意將alert("")換成了,console.log,在firefox和chrome下就通過了。即執行了console.log后,便不再執行默認的提交了,
這里就奇怪了,為什么在中間alert就不行,ie下的alert與firefox,chrome的alert有什么不同呢?應該都是阻塞式的。
我又針對問題測了很久,發現之前的懷疑是錯誤的,alert肯定都是阻塞的,唯一的原因是ie系列下onkeydown與onsubmit是同步的,所以它按照了我所想的邏輯執行,而
firefox,chrome下的onkeydown與onsubmit是異步的,故在alert("")阻擋了onkeydown,但onsubmit()還會繼續執行。
所以我們將代碼改了下,在firefox,chrome下就OK了
document.onkeydown = function(e) { var e = e || event; if(e.keyCode == 13) { setTimeout(function(){ alert("自己的邏輯"); },0); e.preventDefault ? e.preventDefault() : (e.returnValue = false); } }
代碼到這里,大家應該就明白了,javascript的函數調用也是堆棧的,setTimeout可以將函數從堆棧里出來,所以也就解決了異步的問題。
問題解決到這里,得總結一下
一 ie下與firefox,chrome在處理onkeydown與onbsubmit機制不一樣, ie是同步的,而firefox,chrome是異步的,通過一個阻塞的alert(1)就可以說明這個問題。
二 當想改變一個函數執行順序時,包括一些瀏覽器自身的默認順序時,可以通過setTimeout來改變函數在本來堆棧的順序。