網站製作學習誌

記錄學習製作網站的一切

JavaScript 小陷阱 (1) - 為什麼資料會送出兩次?

有一次,我同事作了一個活動網頁,那是要在一個表單上填寫一些個人資料,通過驗證後就送出。可是不論怎麼送,就是會出現這個人已經填寫過資料。

我們大家就一起幫他檢查程式,可是不論是 SQL 語法或是程式流程,都找不到問題。我們大家直喊看到鬼,有人甚至考慮要去廟裡拜拜,比較有理性的人則認為是不是我們不知覺地啟動了資料庫的某個機制。

註:可以參考看看這篇文章「不要搞封建迷信活动」。

當然,問題並沒有這麼複雜,我們幾個決定暫時先冷靜下來,從最簡單的地方開始找起。

結果我們看到了以下的 HTML 與 JavaScript :

1
2
3
4
5
6
7
8
9
10
11
<script type="text/javascript">
function checkForm (fm) {
    // ... 略
    fm.submit();
    return false;
}
</script>
<form name="form1" method="post" action="process.php" onsubmit="checkForm(this);">
<!-- 略 -->
<input type="submit" value="送出" />
</form>

不曉得大家看出什麼端倪沒有?答案就在 fm.submit 和 onsubmit 上面。

問題有兩個:

  1. 在 check function 裡,其實不應該去執行 submit 的動作,我們要很單純地回傳 true 或 false 值即可。
  2. 在函式會回傳 true 或 false 值時, onsubmit 要做接收的動作,也就是以下這樣才是正確的寫法:
    1
    
    onsubmit="return checkForm(this);"
    在 onsubmit 事件接收到 false 值之後,就會取消 submit 的動作,所以表單也就不會被送出。

而原來的做法,因為 onsubmit 沒有收到函式的回傳的 false 值,因此它還是會乖乖的送出表單資料。但是在 checkForm 函式已經先行送出一次了,伺服端就會先執行一次新增的動作;所以第二次送出的資料就會造成重複的問題。

有些人習慣在按下 submit button 去驗證表單資料,這也沒什麼不可以,只要記住上面的原則即可。例如:

1
<input type="submit" value="送出" onclick="return checkForm(this.form);" />

我們可以利用 this.form 來取得 submit button 所屬的表單,這樣一來按下送出鍵時,就會和上面的 onsubmit 做一樣的檢查動作。

不過千萬不要在 form 標籤的 onsubmit 再做一次 checkForm ,那是沒有必要的。

不過ㄚ凱幫我想到一件事:如果有人按下 Enter 鍵送出表單,利用 submit button 來檢驗表單的動作就沒用了。因此還是改用上面的 onsubmit 會比較好一點。

Comments