[Javascript] 為什麼在 <input type="date"> 中,iOS Safari 需要用 blur 而不是 change?

2025-07-07

最近遇到,iOS 上的 safati 的一個雷,原來在 <input type='date'> 中的 change 上面定義上跟其他瀏覽器有點不同!

在前端處理日期輸入驗證時,我們通常會監聽 <input type="date"> 的 change 事件

當使用者選擇完日期後,即執行驗證流程。然而,在 iOS Safari 上

使用 change 監聽日期輸入卻常常造成錯誤或過早觸發,導致錯誤的驗證結果或錯誤提示

change 事件會在 使用者修改完表單欄位並確認變更後 才觸發,一般我都會寫在這事件上面

後來我發現有一些問題,問了GPT才知道會有以下問題

在 iOS Safari 上,<input type="date"> 有兩個特別且公認的問題

問題一:change 事件會「過早觸發」
iOS Safari 的日期選擇器在使用者還未選定日期時,就可能觸發 change。

問題二:value 會自動填入今天日期
解決方案就是改用 blur 讓他跟其他瀏覽器都維持一致的結果

範例程式碼:

input.addEventListener("blur", function () { let raw = this.value; if (!raw) return; // iOS 使用者沒選日期 &#8594; 不檢查 // ...其餘格式化與 min/max 驗證... });


這邊是我判斷讓客戶必須選取只有明天跟加上兩周的日期

function TwoWeekCheck() { var input = document.getElementById(&quot;txtBookingDate&quot;); var today = new Date(); var twoWeeksLater = new Date(); twoWeeksLater.setDate(today.getDate() +14); // 明天 var tomorrow = new Date(); tomorrow.setDate(today.getDate() + 1); input.min = formatDate(tomorrow); input.max = formatDate(twoWeeksLater); const inputDate = document.querySelector(&quot;input[type=&#39;date&#39;]&quot;); // 使用者選完日期後才會觸發 blur&#65292;最安全 inputDate.addEventListener(&quot;blur&quot;, function () { let raw = this.value; // iOS Safari 若僅打開選擇器但未選日期 &#8594; value會是空&#65292;不要驗證 if (!raw) return; // 若是未補零的格式&#65292;補成 yyyy-mm-dd let parts = raw.split(&quot;-&quot;); if (parts.length !== 3) return; const y = parts[0]; const m = parts[1].padStart(2, &quot;0&quot;); const d = parts[2].padStart(2, &quot;0&quot;); const val = `${y}-${m}-${d}`; const min = this.getAttribute(&quot;min&quot;); const max = this.getAttribute(&quot;max&quot;); if ((min &amp;&amp; val &lt; min) || (max &amp;&amp; val &gt; max)) { toastr.error(`日期必須在 ${min} ~ ${max} 之間`); this.value = &quot;&quot;; this.focus(); } });


結論:

change 在 iOS Safari 的 <input type="date"> 上是 "不可靠的",尤其在 input type='date' 

這邊筆記一下,之後印象比較深刻



當麻許的碎念筆記 2014 | Donma Hsu Design.