Vue3中computed过滤数据报错:obj.filter is not a function
问题分析与解决
报错根源
控制台的TypeError: obj.filter is not a function明确说明:你调用filter的obj不是数组——filter是数组专属方法,对象无法调用。
你的问题出在把ref定义的数组转成reactive对象的操作上:如果products是ref([])定义的数组,直接执行const obj = reactive(products)会把ref对象包装成一个带value属性的响应式对象(结构为{ value: [产品数组] }),而非数组本身,自然无法使用filter。
解决方案
方案1:直接使用ref数组(推荐,无需多余转换)
ref完全可以处理数组的响应式,转成reactive属于冗余操作,直接简化代码即可:
<script setup> import { ref, onMounted, computed, useRoute } from 'vue' import ApiService from '@/services/ApiService' const route = useRoute() // 初始化ref数组 const products = ref([]) onMounted(async () => { // 假设接口返回直接是产品数组,如果接口返回是{ data: [...] },则取res.data const res = await ApiService.getProduct() products.value = res }) // 过滤逻辑的计算属性 const searchedProducts = computed(() => { const targetId = route.params.productId // 先判断数组是否有效,避免初始空值报错 if (!Array.isArray(products.value)) return [] // 如果没有路由参数,返回全部产品 if (!targetId) return products.value // 注意:如果产品id是数字类型,需要把targetId转成Number(targetId)再比较 return products.value.filter(item => item.id === targetId) }) </script>
方案2:如果一定要用reactive数组
直接初始化reactive数组,不要从ref对象转换:
<script setup> import { reactive, onMounted, computed, useRoute } from 'vue' import ApiService from '@/services/ApiService' const route = useRoute() // 直接初始化reactive数组 const products = reactive([]) onMounted(async () => { const res = await ApiService.getProduct() // 用splice修改原数组,保持响应式 products.splice(0, products.length, ...res) }) const searchedProducts = computed(() => { const targetId = route.params.productId if (!Array.isArray(products)) return [] if (!targetId) return [...products] // 返回新数组避免直接修改原响应式数组 return products.filter(item => item.id === targetId) }) </script>
额外注意事项
- 确认接口返回的是数组:如果接口返回的是嵌套对象(比如
{ code: 200, data: [产品列表] }),需要取出data部分再赋值给products - 路由参数类型匹配:
route.params.productId是字符串类型,如果你的产品id是数字,要转成Number(targetId)再做比较 - 初始状态判断:在计算属性里先判断数组是否有效,避免页面初始化时
products为空导致的报错
内容的提问来源于stack exchange,提问作者Aaron
相关产品推荐
相关产品推荐

