dayjs不能在filters中直接import,因uni-app过滤器不支持es module;应提前挂载到uni.$dayjs或封装工具函数导出,且需兼容多类型时间输入、避免插件方法、注意格式符大小写及中文引号处理。

dayjs 不能直接在 filters 里 import
很多人一上来就在 filters 里写 import dayjs from 'dayjs',结果 H5 正常、小程序报错、iOS 真机白屏。原因很直接:uni-app 的过滤器是纯函数上下文,不支持 ES Module 动态导入,且在非 Vue 实例中无法访问模块作用域。
正确做法是提前把 dayjs 实例或函数挂到全局可访问位置:
- 在
main.js或app.js中初始化并挂载:uni.$dayjs = dayjs - 或封装成工具函数导出,在
filters中import { formatDate } from '@/utils/date'(注意:必须是具名/默认导出,不能在 filter 内部 import) - 别用
require('dayjs')—— 在某些平台(如微信小程序)会触发构建异常
过滤器里传参必须兼容时间戳、字符串、Date 对象
dayjs() 构造器对输入类型敏感,但业务中后端返回的可能是时间戳(number)、ISO 字符串("2026-09-04T17:51:00Z")、短横线格式("2026-09-04"),甚至空值。直接 dayjs(date).format(...) 在 iOS 上遇到 "2026-09-04" 会解析为 UTC 时间,显示成 9 月 3 日。
安全写法要先做归一化:
- 显式判断类型:
if (typeof date === 'string' && date.includes('-')) date = date.replace(/-/g, '/') - 兜底转时间戳:
const ts = Number(date) || Date.parse(date) - 再交由
dayjs(ts)处理,避免依赖原生Date构造行为
示例过滤器逻辑:
使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
export const formatDate = (date, format = 'YYYY-MM-DD') => {
if (!date) return ''
const ts = typeof date === 'number' ? date : Date.parse(date.replace(/-/g, '/'))
return uni.$dayjs(ts).format(format)
}
过滤器里别用 dayjs 插件做相对时间
像 fromNow()、calendar() 这类插件方法需要额外引入(如 import 'dayjs/plugin/relativeTime'),且内部依赖 Date.now() 频繁调用。放在过滤器里会导致:
- 每次模板重渲染都执行一次相对计算,性能浪费
- 插件未正确 install 时静默失败(无报错,只返回原始值)
- “刚刚”“5分钟前”这类文案需定时刷新,过滤器做不到响应式更新
真正需要人性化显示的场景,应该:
- 用
<uni-dateformat></uni-dateformat>组件(它内部已处理好定时器和跨平台差异) - 或在
methods/setup()中调用,并配合onMounted+setInterval主动刷新 - 过滤器只做静态格式化,比如
{{ time | formatDate('YYYY年MM月DD日') }}
格式字符串大小写和占位符容易写错
dayjs 的格式符区分大小写,而且和原生 Date.prototype.toLocaleString() 不同。常见翻车点:
-
DD是「当月第几天」(01–31),dd是「星期几数字」(0–6),写成YYYY-MM-dd会输出年月+星期几,不是日期 -
HH是 24 小时制,hh是 12 小时制;mm是分钟,MM是月份 —— 混用会导致"2026-09-04 17:09"变成"2026-17-04 09:09" - 中文字符(如
年月日)要放在引号外,否则会被当成占位符忽略:'YYYY"年"MM"月"DD"日"'
建议开发期加一层校验:
const safeFormat = (date, fmt) => {
if (!fmt || typeof fmt !== 'string') return uni.$dayjs(date).format()
return uni.$dayjs(date).format(fmt)
}
最麻烦的从来不是写对一个格式化函数,而是让所有接口返回的时间字段都走同一套解析逻辑——从 API 响应拦截器 就统一转成时间戳,比在每个 filter 里补丁强得多。










