
Safari 对 <input type="date"> 的空值校验异常严格,手动将 v-model 设为空字符串不会重置其内部 ValidityState,导致表单被阻止提交;Chrome 等浏览器则兼容性更好。本文提供两种稳定、可落地的修复方案。
safari 对 `` 的空值校验异常严格,手动将 `v-model` 设为空字符串不会重置其内部 validitystate,导致表单被阻止提交;chrome 等浏览器则兼容性更好。本文提供两种稳定、可落地的修复方案。
在 Vue 项目中使用 <input type="date"> 时,若通过 v-model 绑定并手动清空(如 createdAt.value = ''),Safari(尤其是 17.2.1 及后续版本)会出现一个隐蔽但关键的问题:表单无法提交——点击“Save”按钮无响应,@submit.prevent 事件甚至不会触发。而相同逻辑在 Chrome、Firefox 或 React 中均正常运行。
根本原因在于:Safari 将空字符串 '' 视为无效日期值,且不会自动重置 <input> 元素的 ValidityState.valid 状态(即使 value 已为空)。当表单提交时,Safari 会因该字段 validity.badInput === true 而静默阻止提交,不抛错、不触发事件,极难排查。
✅ 推荐方案一:禁用原生表单验证(简洁可靠)
为 <form> 添加 novalidate 属性,彻底绕过浏览器对 type="date" 的强制校验,由 Vue 逻辑统一控制数据有效性:
<template>
<form @submit.prevent="submit" novalidate>
<label for="createdAt">CreatedAt</label>
<input id="createdAt" type="date" v-model="createdAt" />
<button type="button" @click="clear">Clear</button>
<button type="submit">Save</button>
</form>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const createdAt = ref<string>('')
const submit = () => {
// ✅ 此处可安全执行:createdAt.value 为 '' 或 'YYYY-MM-DD'
console.log('Submitted:', createdAt.value || '(empty)')
}
const clear = () => {
createdAt.value = ''
}
</script>⚠️ 注意:novalidate 仅禁用浏览器原生验证(如 required、日期格式检查),不影响 Vue 的业务校验逻辑。你仍可在 submit() 中自行判断 createdAt.value 是否符合业务规则(例如非空校验、范围校验等)。
✅ 推荐方案二:使用原生 <button type="reset">(语义清晰)
若表单仅含日期字段或你希望整体重置,改用原生重置按钮更符合 HTML 规范,且 Safari 对 reset 行为支持完善:
<template>
<form @submit.prevent="submit">
<label for="createdAt">CreatedAt</label>
<input id="createdAt" type="date" v-model="createdAt" />
<!-- 移除自定义 clear 方法,改用原生 reset -->
<button type="reset">Clear</button>
<button type="submit">Save</button>
</form>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const createdAt = ref<string>('')
const submit = () => {
console.log('Submitted:', createdAt.value)
}
</script>此时无需 clear() 方法,<button type="reset"> 会将所有表单控件(包括 type="date")恢复为初始值(即空字符串),且 Safari 会正确更新其 ValidityState,确保后续提交可用。
立即学习“前端免费学习笔记(深入)”;
? 补充说明与最佳实践
- ❌ 避免直接操作 DOM 或调用 inputElement.setCustomValidity('') —— Vue 响应式系统与原生 API 混用易引发状态不一致;
- ✅ 若需保留自定义清空逻辑(如仅清空日期而不重置其他字段),方案一(novalidate)是唯一健壮选择;
- ? 验证技巧:可在 DevTools Console 中执行 document.getElementById('createdAt').validity 查看 Safari 下清空后的实际状态,确认 badInput: true 是问题根源;
- ? 此行为属 Safari 已知兼容性差异(WebKit Bug #254638),非 Vue 缺陷,故优先通过 HTML 层面规避而非框架层 hack。
综上,novalidate 是兼顾兼容性、可控性与开发效率的首选方案;而 type="reset" 则适合简单表单场景。二者均能确保 Vue + Safari 下日期表单提交行为与 Chrome 保持一致。


















