ios safari 不支持 new date("2026-04-21") 等短横线格式,需先 replace(/-/g, '/') 或判断时间戳再解析;formatdate 过滤器须手动补零、避免 tolocalestring 和 toisostring;相对时间逻辑不应放入过滤器;全局过滤器仅模板可用,工具函数需单独封装。

过滤器里 new Date() 为什么在 iOS 上返回 Invalid Date
因为 iOS Safari 不支持直接解析 "2026-04-21" 这类带短横线的字符串时间,只认 "2026/04/21" 或纯数字时间戳。很多开发者把后端返回的字符串(如 "2026-04-21T10:30:00")和时间戳混着塞进同一个过滤器,结果在真机上 new Date("2026-04-21") 直接崩成 Invalid Date。
必须先做类型判断和标准化:
- 用
/^\d+$/.test(date)判断是不是纯数字(时间戳) - 是字符串就先
date.replace(/-/g, '/'),再传给Date.parse() - 得到毫秒数后统一走
new Date(ts),别让构造函数自己猜
formatDate 过滤器必须手动补零,不能靠 toLocaleString
date.toLocaleString() 在 iOS 和 Android 上返回格式不一致,且无法控制分隔符和位数;toISOString().slice(0, 19).replace('T', ' ') 默认输出 UTC 时间,比本地快 8 小时——这两个都得避开。
年月日时分秒全部显式补零,推荐写法:
- 月份:
(date.getMonth() + 1).toString().padStart(2, '0') - 日期/小时/分钟/秒:
date.getDate().toString().padStart(2, '0') - 不要写
date.getFullYear() + '-' + (date.getMonth()+1) + '-',否则会出2026-5-30
过滤器不适合处理“刚刚”“昨天”这类相对时间
过滤器设计初衷是无副作用、轻量、同步转换。但“刚刚”“3小时前”这类逻辑依赖当前时间(Date.now()),且需多层 if 判断阈值,放进过滤器容易导致模板重渲染异常,尤其在列表滚动时性能抖动明显。
更稳妥的做法:
- 简单绝对格式(如
yyyy-MM-dd HH:mm:ss)可用过滤器 - 相对时间逻辑放
methods或工具函数里,配合computed或onMounted+ 定时器更新 - 直接用
uni-dateformat组件,它的threshold必须传数组,比如[0, 3600000]表示 0ms 内显示“刚刚”,1 小时内显示“X分钟前”
全局过滤器注册后,在非 Vue 实例里不可用
你在 main.js 里用 Vue.filter('formatDate', ...) 注册了过滤器,它只在模板中生效。一旦进到 store/action、request 拦截器、utils 工具函数里,{{ ts | formatDate }} 就完全失效。
这时候必须:
- 单独封装一个纯函数,比如
export function formatDate(date, fmt = 'yyyy-MM-dd HH:mm:ss') - 在需要的地方
import { formatDate } from '@/utils/date' - 避免挂到
Date.prototype,TypeScript 类型不识别,且易被其他库覆盖
真正麻烦的不是写不出 format 函数,而是跨端时 iOS 对字符串时间的解析行为和你写的过滤器逻辑对不上——补零、时区、类型判断,漏掉任何一环,真机就给你颜色看。










