uni-app中不能用过滤器(|)去重数组,应使用computed中filter+findindex或map实现;因过滤器仅支持单值格式化,无this上下文且不响应数组变化。

filter 本身不是过滤器(filter 是数组方法),uni-app 的「过滤器」(| 管道符)只适合格式化单个值,比如日期、价格、字符串截断,**不能用来去重数组**。硬套会报错或无效。
下面直接说清楚该怎么做、为什么、以及最容易栽坑的地方。
uni-app里别用 Vue 过滤器做数组去重
Vue 的 filters 只接收一个输入值,返回一个转换后值,例如:{{ item.price | toFixed }}。你没法把整个数组传进去再吐出一个去重后的新数组——filters 没有 this 上下文、不响应数组变化、也不能调用 findIndex 或 Set 等操作。
常见错误写法(无效):
{{ list | uniqueBy('id') }}
这会直接报 TypeError: Cannot read property 'id' of undefined 或静默失败。
真正能用的数组去重方式(推荐 2 种)
在 computed 或 methods 中处理,确保响应式更新和性能可控。
- 按某个字段去重(如
id),用filter+findIndex最稳妥:
computed: {
uniqueList() {
return this.rawList.filter((item, index, arr) =>
arr.findIndex(v => v.id === item.id) === index
);
}
}
✅ 优点:语义清晰、兼容性好(支持所有 uni-app 平台)、不依赖外部库
❌ 注意:如果 rawList 很大(>1000 条),findIndex 每次都遍历,会有轻微性能开销
- 用
Map实现 O(n) 去重(更高效,推荐):
computed: {
uniqueList() {
const seen = new Map();
return this.rawList.filter(item => {
if (seen.has(item.id)) return false;
seen.set(item.id, true);
return true;
});
}
}
✅ 优势:只遍历一次,比 findIndex 快;Map 在所有 uni-app 目标平台(微信小程序、App、H5)都支持
❌ 注意:别用 Object 当哈希表(比如 seen[item.id] = true),数字 key 可能被 toString 强转,导致 {'1': true, 1: false} 这类意外覆盖
为什么不用 Set + JSON.stringify?
网上常看到这种写法:
[...new Set(this.rawList.map(i => JSON.stringify(i)))].map(JSON.parse)
它在 uni-app 里容易出问题:
- 对象属性顺序不一致时,
JSON.stringify结果不同 → 去重失效(比如{a:1,b:2}和{b:2,a:1}被当成两个不同项) - 含
Date、undefined、函数、RegExp时直接序列化失败或丢失数据 - 小程序端
JSON.parse对某些嵌套结构容错性差,偶发白屏
除非你 100% 确认数组里全是简单扁平对象且字段顺序固定,否则绕开它。
如果用了 lodash,_.uniqBy 可以但要注意
安装后确实简洁:
import { uniqBy } from 'lodash'
但在 uni-app 小程序端,lodash 的体积较大(gzip 后约 20KB),可能拖慢首屏。如果只是去重,没必要引入整包。
更轻量的做法是单独引入方法(需配置 babel 插件或使用 esm 版本):
import uniqBy from 'lodash/uniqBy'
但多数项目里,手写 Map 方案更省事、更可控。
去重逻辑本身不复杂,关键在于别混淆「Vue 过滤器」和「数组方法」的职责边界——前者只做展示层转换,后者才管数据结构操作。










