应封装为工具函数formatEmpty而非过滤器,判断null、undefined、''及空白字符串并转全角破折号“—”,数字布尔值不转换,避免模板中重复创建函数。

uni-app里怎么用filter写一个通用空值转破折号的过滤器
直接在main.js或utils/filters.js中定义全局过滤器,避免每个页面重复写逻辑。uni-app 3.0+ 已默认不支持 Vue 2 风格的Vue.filter,所以必须用app.config.globalProperties(Vue 3 兼容写法)或封装成函数调用。
常见错误是直接在模板里写{{ item.name || '—' }}——这无法处理null、undefined、空字符串、空数组、空对象等所有“falsy”但语义上需要展示破折号的场景。
- 推荐封装为工具函数而非过滤器:更易测试、Tree-shaking、支持 TypeScript 类型推导
- 破折号建议用全角
—(U+2014)或短横线-,别用连字符-(U+002D)或减号,否则在某些字体下显示过细 - 不要对
0、false做转换——它们是有意义的合法值,仅当业务明确要求才特殊处理
怎么判断才算“空”:isEmpty的合理边界在哪
不能简单用!value,比如0、false、'0'都可能被误判。实际项目中,“空”的判定应聚焦于:数据未提供 / 字段缺失 / 显式为空,而不是逻辑假值。
典型需转破折号的值包括:null、undefined、''(空字符串)、[](空数组,仅当业务约定数组为空即无数据时)、{}(空对象,同理)。
-
Array.isArray(value) && value.length === 0→ 空数组(按需启用) -
typeof value === 'object' && value !== null && Object.keys(value).length === 0→ 空对象(慎用,多数场景对象存在即有效) - 字符串要先
.trim()再判断,避免' '类空白字符漏判 - 数字类型(
number)和布尔类型(boolean)一律不转,除非你明确知道0代表“无值”
在 template 中怎么安全调用:别在v-for里反复创建函数
不要这样写:{{ formatEmpty(item.name) }}且把formatEmpty定义在methods里——每次渲染都会新建闭包,影响性能,尤其列表长时明显。
正确做法是把格式化逻辑提到computed或setup中预处理数据,或直接用纯函数导入:
// utils/format.js
export function formatEmpty(value, placeholder = '—') {
if (value == null) return placeholder
if (typeof value === 'string' && value.trim() === '') return placeholder
return value
}
然后在setup中:
import { formatEmpty } from '@/utils/format'
// ...
return () => (
<view>{formatEmpty(props.item.name)}</view>
)
或者在模板中(需确保已全局挂载):
{{ $formatEmpty(item.name) }}
为什么不用 computed 或 watch 做字段级空值处理
对单个字段用computed包装看似清晰,但会显著增加响应式开销:每个computed都建立依赖追踪,当数据量大或嵌套深时,内存与计算成本上升明显。
更关键的是——它把展示逻辑侵入了状态层。同一份数据可能在不同页面有不同空值展示需求(比如A页用—,B页用暂无),硬绑定到computed会导致复用困难。
- 展示层该负责展示,数据层该负责真实值
- 过滤逻辑放在
utils里,按需导入,按需传参,才是松耦合 - 如果项目已用 Pinia,也别在 store 里做空值转换——store 应保持数据原始性
真正容易被忽略的一点:后端返回的"null"(字符串)不是null,它会被当成有效字符串显示出来。这类情况得靠接口层统一清洗,或在formatEmpty里加一条value === 'null'判断——但这属于数据契约问题,不是过滤器该兜底的。










