Vue3+TS组合式函数返回数组调用filter报错,求助排查
问题原因及解决方法
1. 初始化错误:favorites 被初始化为对象而非数组
在组合式函数中,你将 favorites 初始化为 ref({})(空对象),但它的实际用途是存储艺术家数组。尽管后续 loadFavorites 会将其赋值为数组,但在初始化阶段或数据加载完成前,尝试对对象调用 filter 方法必然会报错。
修复: 将初始值改为空数组:
const favorites = ref([]);
2. 错误访问 Ref 内部值
在组件中,你通过 favorites._rawValue 访问数组,这是直接操作 Vue 的内部属性,不符合规范。正确的做法是通过 .value 访问 Ref 的值(在 <script setup> 中,模板会自动解包,但在脚本中必须手动使用 .value)。
修复: 修改 isFavorite 函数:
function isFavorite(artist) { return favorites.value.filter((favorite) => { return favorite.id === artist.id; }).length > 0; }
3. 监听逻辑错误
你当前的监听目标是 favorites.value,这意味着你监听的是初始的空对象。当后续将数组赋值给 favorites.value 时,监听绑定的是旧对象的引用,不会触发缓存逻辑。此外,如果通过 push 修改数组(如 addFavorite 中的操作),由于数组引用未变,浅监听也无法触发。
修复: 直接监听 Ref 实例,并开启深度监听:
watch(favorites, cacheFavorites, { deep: true });
完整修正代码
组合式函数(composable)
import { onMounted, ref, watch } from 'vue'; import { Preferences } from "@capacitor/preferences"; import { useStore } from "@/store"; export const userFavorites = () => { const FAVORITE_ARTISTS = 'favorites'; // 修正:初始化为空数组 const favorites = ref([]); const store = useStore(); function addFavorite(artist, saved) { let payload = { artists: [artist], isFavorite: saved }; store.dispatch({ type: 'updateUserFavorites', payload }); favorites.value.push(artist); } const loadFavorites = async () => { const favoriteList = await Preferences.get({ key: FAVORITE_ARTISTS }); const favoriteResults = favoriteList.value ? JSON.parse(favoriteList.value) : []; favorites.value = favoriteResults; }; const cacheFavorites = () => { Preferences.set({ key: FAVORITE_ARTISTS, value: JSON.stringify(favorites.value), }); }; onMounted(loadFavorites); // 修正:监听 Ref 并开启深度监听 watch(favorites, cacheFavorites, { deep: true }); return { favorites, addFavorite }; };
Vue 组件(myfile.vue)
<script lang="ts" setup> import { computed, ref } from "vue"; import RegisterToolbar from "@/components/RegisterToolbar.vue"; import { useRoute, useRouter } from "vue-router"; import { useStore } from "@/store"; import { bookmarkOutline, bookmark } from 'ionicons/icons'; import { userFavorites } from '@/composables/userFavorites'; const { addFavorite, favorites } = userFavorites(); import { IonButton, IonBackButton, IonButtons, IonPage, IonIcon, IonContent, IonLabel, IonAvatar, IonCard, IonGrid, IonRow, IonCol, IonList, IonItem, IonCardHeader, IonChip, IonCardContent, IonSearchbar, } from "@ionic/vue"; const store = useStore(); const router = useRouter(); const artists = computed(() => store.getters.getArtists); const user = computed(() => store.getters.getUser); const route = useRoute(); // 修正:通过 .value 访问 Ref 值 function isFavorite(artist) { return favorites.value.filter((favorite) => { return favorite.id === artist.id; }).length > 0; } const navigate = (url: string) => { router.push(url); } </script>
内容的提问来源于stack exchange,提问作者caro
相关产品推荐
相关产品推荐

