过滤器访问未定义值会静默传入undefined,后续调用.replace()等才报错;根本原因是过滤器不自动处理null/undefined,需手动加空值守卫,且小程序不支持自定义filters。

过滤器里访问未定义的值,不是语法错误,而是运行时静默失败——undefined被原样传入,后续调用.replace()、.length或拼接字符串时才爆错。根本原因就一个:你把它当“安全转换器”用了,但它连基本的空值防御都不做。
过滤器函数内部没做空值判断
uni-app 的过滤器(Vue.filter)是纯同步函数,不自动解包、不处理 null 或 undefined。比如写了个格式化手机号的过滤器:
Vue.filter('formatPhone', value => value.replace(/(\d{3})(\d{4})(\d{4})/, '$1-$2-$3'))
一旦传入 undefined,立刻报 Cannot read property 'replace' of undefined。
- 所有入参必须手动加守卫:
value == null ? '' : value.toString().replace(...) - 别依赖后端永远返回 string——接口字段可能缺失、字段类型可能为 number 或 null
- 如果过滤器要处理对象属性(如
user?.profile?.phone),必须先判空再取值,不能直接写value.phone
模板中传了未初始化的响应式变量
常见于 ref(null) 或 data() { return { user: null } } 场景。模板一渲染,{{ user.phone | formatPhone }} 就拿到 undefined.phone,过滤器还没开始执行就崩了。
- 初始化时给默认值:
ref({ phone: '' })或data() { return { user: { phone: '' } } } - 用可选链 + 空值合并:
{{ user?.phone ?? '' | formatPhone }}(注意:这仅在支持可选链的平台有效,小程序需降级) - 更稳妥的是提前转换:
computed(() => user.value?.phone || ''),再把 computed 结果传给过滤器
在 v-if / v-for 里误用过滤器结果做条件
v-if="item.status | statusText === '已支付'" 这种写法不仅语法非法,还会让编译器把整个表达式当字符串丢弃,最终 v-if 拿到 undefined,变成 v-if="undefined" → 始终为 false,且不报错。
-
v-if和v-for不走过滤器管道,只认 JS 布尔表达式 - 状态映射逻辑必须前置:用
computed或methods返回布尔值,例如isPaid(item) - 小程序平台压根不支持自定义 filters,这种写法在真机上直接失效,连 warning 都没有
跨平台时过滤器未按条件编译
你在 H5 写了一个依赖 Intl 的日期过滤器,但微信小程序基础库低于 2.18.0 时 Intl 不可用,new Intl.DateTimeFormat() 报错,导致整个过滤器返回 undefined。
- 对原生 API 调用必须包裹
#ifdef:#ifdef H5用Intl,#ifndef H5用简单字符串拼接 - 不要在过滤器里调
uni.getSystemInfoSync等平台 API——过滤器无平台上下文,uni可能为undefined - 若需平台差异逻辑,应封装成工具函数,在
setup或onLoad中预先判断并缓存结果
最常被忽略的一点:过滤器不是“兜底层”,它没有生命周期、不感知响应式、不处理异步、也不做类型校验。任何指望它自动容错的写法,都会在某个真机环境、某次接口变更、某个基础库升级后突然失效。


















