You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue中计算属性过滤是否覆盖原数组?如何基于API原始数组重过滤?

解决Vue中基于原始数组的响应式过滤问题

嘿,我一眼就看出问题出在哪了——你在过滤的时候直接修改了原始数组里的嵌套属性!

你看这段代码:

feature.properties.site_observations = feature.properties.site_observations.filter(...)

因为数组和对象都是引用类型,这行代码会直接把this.features里的原始site_observations给替换掉。当你清空搜索词再输入新内容时,你过滤的已经是被修改过的数组,而不是API返回的原始数据了,这就导致了错误的结果。

解决思路:不碰原始数据,基于副本处理

我们的核心原则是:永远不要直接修改用于过滤的原始数据源,所有过滤操作都在副本上进行。

方案1:仅筛选出包含匹配项的Feature(不修改Feature内部的观测列表)

如果你只需要把有匹配观测记录的Feature保留下来,不需要修改Feature里的site_observations内容,那可以简化成这样:

filteredFeatures() {
  // 先处理空搜索词的情况,直接返回原始数组
  if (!this.searchTerm.trim()) {
    return this.features
  }
  // 基于原始数组过滤,不修改任何原始数据
  return this.features.filter(feature => {
    // 只检查site_observations是否有匹配项,不修改原数组
    const hasMatch = feature.properties.site_observations.some(el => 
      JSON.stringify(el).match(new RegExp(this.searchTerm, 'i'))
    )
    return hasMatch
  })
}

这里用some替代filter,因为我们只需要知道有没有匹配项,不需要生成新的数组,性能也更好一点。

方案2:筛选Feature同时保留匹配的观测记录

如果你需要在保留Feature的同时,只展示匹配的site_observations,那就要对每个Feature做深拷贝,避免修改原始数据:

filteredFeatures() {
  if (!this.searchTerm.trim()) {
    return this.features
  }
  return this.features.map(feature => {
    // 深拷贝Feature对象,彻底和原始数据断开引用
    const copiedFeature = JSON.parse(JSON.stringify(feature))
    // 在拷贝后的对象上过滤观测记录
    copiedFeature.properties.site_observations = copiedFeature.properties.site_observations.filter(el => 
      JSON.stringify(el).match(new RegExp(this.searchTerm, 'i'))
    )
    return copiedFeature
  }).filter(feature => feature.properties.site_observations.length > 0)
}

这里用JSON.parse(JSON.stringify())做深拷贝是最简单的方式,适合没有循环引用的GeoJSON对象。如果你的数据有循环引用,可以用Vue2的Vue.util.extend(true, {}, feature)或者引入lodash的cloneDeep方法。

为什么之前用Object.assign没生效?

因为Object.assign()是浅拷贝,只能复制第一层属性,对于嵌套的site_observations数组,还是会和原始数据共享引用。所以必须用深拷贝才能彻底断开和原始数据的关联。

内容的提问来源于stack exchange,提问作者Peter Donovan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 15:57:59