秒级搜索过滤需解耦数据与视图、预判条件、节流渲染:空值快速返回原始数组;关键词与字段统一转小写预处理;万级列表必用v-memo;搜不到时引导远程搜索。

用计算属性实现秒级搜索过滤,关键不在“写得多”,而在“算得巧”——尤其面对万级数据时,靠纯 filter() 硬刷会卡顿。真正高效的方案是:数据与视图解耦 + 条件预判 + 渲染节流。
空值快速返回,避免无意义遍历
搜索框为空或只含空白字符时,直接返回原始数组引用,不触发任何过滤逻辑。这省去了遍历开销,也避免了 Vue 重渲染不必要的 diff。
- 用
this.searchTerm.trim() === ''判断,比!this.searchTerm更严谨(防空格输入) - 返回
this.list原始引用,而非[...this.list]或this.list.slice(),减少内存分配
字段匹配前统一预处理,减少重复计算
对搜索关键词和每项字段都只转一次小写,避免在 includes() 中反复调用 toLowerCase()。复杂场景下可提前构建搜索索引字段(如 searchKey: item.name + ' ' + item.category),再统一匹配。
- 示例写法:
const keyword = this.searchTerm.trim().toLowerCase(); - 匹配时用
item.searchKey?.includes(keyword),比多字段||连接更简洁、更易扩展
万级列表必须配合 v-memo(Vue 3.2+)
仅靠 computed 优化不够——它只管“算得快”,不管“渲得多”。v-memo 能让 v-for 跳过未变化的节点,大幅降低重绘压力。尤其适合商品、城市等静态结构强的列表。
- 模板中这样写:
<li v-for="item in filteredList" :key="item.id" v-memo="[item.id, item.name]"> - 搭配 computed 中的空值判断,二者协同才能把 16000 条城市列表的响应压进毫秒级
搜不到时引导远程搜索,不硬扛全量过滤
本地过滤是“快”,但不是“全”。当 filteredList.length === 0 且关键词有一定长度(如 ≥2 字),显示“搜不到?去全网找”按钮,点击后才发起后端模糊查询。这既保体验,又减前端负担。
- 按钮逻辑独立于 computed,不污染响应式链路
- 后端应走全文索引(如 MySQL 的 FULLTEXT 或 Elasticsearch),而非
LIKE '%xxx%'









