Vue3中如何过滤ref()存储的Proxy响应式数据获取单条记录
问题背景
项目中使用ref()存储从Firebase获取的数据,尝试按id过滤获取单条记录时返回结果不符合预期:预期返回单个匹配的对象,实际结果存在异常。
原始实现代码:
const topicalData = ref<Array<any>>() const topicalDataLength = ref(0) const questions = ref() topical.onSnapshot((snapshot) => { topicalData.value = snapshot.docs.map((doc) => { const data = doc.data() const id = doc.id return { id, ...data } }) topicalDataLength.value = topicalData.value.length }) const loadQuestions = (id: string) => { questions.value = topicalData.value?.map((data) => { return data.id == id ? data : false }) console.log(questions.value) // questionTopical.value = true }
当前在loadQuestions方法中使用map遍历ref包裹的响应式数组topicalData做id匹配,无法得到预期的单个对象结果。
问题根因
- 数组方法误用:
Array.map()的设计用途是对数组逐元素做转换,返回与原数组长度完全一致的新数组。当前写法中,id匹配时返回对应数据项,不匹配时返回false,最终得到的是和源数组等长、混杂目标对象与布尔值false的数组,自然无法得到单个匹配对象。 - 异步时序风险:
topicalData初始化时未设置默认空数组,而Firebase的onSnapshot是异步执行的监听回调,如果在快照数据推送完成前调用loadQuestions,topicalData.value为undefined,即使加了可选链也会导致questions.value被赋值为undefined。
修复方案
获取单条匹配记录应当使用Array.find()方法,该方法会返回数组中第一个满足匹配条件的元素,无匹配项时返回undefined,完全符合获取单条对象的需求。同时给数组类型的ref设置初始空值,规避异步阶段的取值异常。
修正后代码:
// 数组类型ref初始化时赋值空数组,避免异步阶段取到undefined const topicalData = ref<Array<any>>([]) const topicalDataLength = ref(0) const questions = ref() topical.onSnapshot((snapshot) => { topicalData.value = snapshot.docs.map((doc) => { const data = doc.data() const id = doc.id return { id, ...data } }) topicalDataLength.value = topicalData.value.length }) const loadQuestions = (id: string) => { // 用find替代map,直接返回第一个id匹配的对象 questions.value = topicalData.value.find((data) => data.id === id) console.log(questions.value) // questionTopical.value = true }
补充:如果业务需要获取所有id匹配的记录(而非第一条),可以替换为
Array.filter(),注意该方法返回的是所有匹配项组成的数组,而非单个对象。
内容的提问来源于stack exchange,提问作者Robin Singh
相关产品推荐
相关产品推荐

