vue 3 组合 api,传递数据并使其响应
vue 3 composition api, passing data and making it reactive
在我的组件中,我有一个简单的 select 菜单,其中有两个选项(“全部”和“投资”)。这里的想法是从可组合项中获取一组数据,并在屏幕上显示该数据的每一行。如果我在菜单中 select "all" 它显示所有行,如果我 select "Investment" 它将过滤数据并仅显示那些 obj.link == "usa".
一旦我获取数据并将其放入我的组件中,如果我 console.log 数据,它就可以正常工作。如果我 console.log 过滤后的数据,我得到一个空数组。
然后我尝试在我的组件中硬编码数据并测试过滤器功能,它工作正常。所以错误来自于我如何获取数据以及我如何尝试使用它。我曾尝试使用不同的挂钩,例如 onMounted,但没有成功。
这是我的代码的简约示例。
任何建议或建议都非常受欢迎
从我的数据库中获取数据的可组合项如下所示:
import {ref} from 'vue'
import { projectFirestore } from '../firebase/config'
import { collection, getDocs } from "firebase/firestore";
const getActorDocs = () => {
const actorDocs = []
const error = ref(null)
const loadActors = async () => {
try {
const querySnapshot = await getDocs(collection(projectFirestore, "actors"));
querySnapshot.docs.map(doc => {
actorDocs.push(doc.data())
})
} catch (err) {
error.value = err.message
console.log(error.value)
}
}
return { actorDocs, error, loadActors}
}
export default getActorDocs
我的组件:
<template>
<div class="col-2">
<span class="lbl">MA</span>
<select v-model="selectedMA" class="form-select" >
<option value="all">all</option>
<option value="Investment">Investment</option>
</select>
</div>
<p v-for="obj in actorListTest2" :key="obj" :value="obj"> {{obj}} </p>
<template/>
<script >
import {onMounted, onBeforeMount, ref} from 'vue'
import getActorDocs from '../../composables/getActorDocs'
export default {
setup(){
const selectedMA = ref("Investment")
const error = ref(null)
const {actorDocs, loadActors} = getActorDocs()
var actorListTest1 = actorDocs
const actorListTest2 = ref([])
loadActors() // loads actors array into actorDocs
actorListTest2.value = actorListTest1
console.log(actorListTest1) // <----- prints correctly (see image below)
if(selectedMA.value === "all"){
actorListTest2.value = actorListTest1
}else{
actorListTest2.value = actorListTest1.filter(obj => {
return obj.link == selectedMA.value
})
}
console.log(actorListTest2.value) // <----- prints undefined !
return { error, selectedMA, actorListTest2}
}//setup
}
</script>
这是 console.log(actorListTest1) 的输出:
然后这是 console.log(actorListTest2) 过滤后的输出:
这是一个 known problem with console.log
,它不应该用于实时调试对象值。
actorDocs
不是反应式的,在 Vue 中不能与异步操作一起正常工作。副作用应该在生命周期钩子中完成,例如:mounted
.
在当前状态下 getActorDocs
尚未准备好与组合 API 一起使用,因为它仅限于遵循承诺控制流以避免这种竞争情况:
onMounted(async () => {
await loadActors();
console.log(actorListTest2.value);
});
避免这种情况的正确方法是制作 actorDocs
反应数组或 ref:
const actorDocs = reactive([]);
如果需要在副作用中访问过滤值,例如console.log
,这是在观察者中完成的
const actorListTest2 = computed(() => actorDocs.filter(...));
watch(actorListTest2, v => console.log(v));
onMounted(() => {
loadActors();
});
在我的组件中,我有一个简单的 select 菜单,其中有两个选项(“全部”和“投资”)。这里的想法是从可组合项中获取一组数据,并在屏幕上显示该数据的每一行。如果我在菜单中 select "all" 它显示所有行,如果我 select "Investment" 它将过滤数据并仅显示那些 obj.link == "usa".
一旦我获取数据并将其放入我的组件中,如果我 console.log 数据,它就可以正常工作。如果我 console.log 过滤后的数据,我得到一个空数组。
然后我尝试在我的组件中硬编码数据并测试过滤器功能,它工作正常。所以错误来自于我如何获取数据以及我如何尝试使用它。我曾尝试使用不同的挂钩,例如 onMounted,但没有成功。
这是我的代码的简约示例。 任何建议或建议都非常受欢迎
从我的数据库中获取数据的可组合项如下所示:
import {ref} from 'vue'
import { projectFirestore } from '../firebase/config'
import { collection, getDocs } from "firebase/firestore";
const getActorDocs = () => {
const actorDocs = []
const error = ref(null)
const loadActors = async () => {
try {
const querySnapshot = await getDocs(collection(projectFirestore, "actors"));
querySnapshot.docs.map(doc => {
actorDocs.push(doc.data())
})
} catch (err) {
error.value = err.message
console.log(error.value)
}
}
return { actorDocs, error, loadActors}
}
export default getActorDocs
我的组件:
<template>
<div class="col-2">
<span class="lbl">MA</span>
<select v-model="selectedMA" class="form-select" >
<option value="all">all</option>
<option value="Investment">Investment</option>
</select>
</div>
<p v-for="obj in actorListTest2" :key="obj" :value="obj"> {{obj}} </p>
<template/>
<script >
import {onMounted, onBeforeMount, ref} from 'vue'
import getActorDocs from '../../composables/getActorDocs'
export default {
setup(){
const selectedMA = ref("Investment")
const error = ref(null)
const {actorDocs, loadActors} = getActorDocs()
var actorListTest1 = actorDocs
const actorListTest2 = ref([])
loadActors() // loads actors array into actorDocs
actorListTest2.value = actorListTest1
console.log(actorListTest1) // <----- prints correctly (see image below)
if(selectedMA.value === "all"){
actorListTest2.value = actorListTest1
}else{
actorListTest2.value = actorListTest1.filter(obj => {
return obj.link == selectedMA.value
})
}
console.log(actorListTest2.value) // <----- prints undefined !
return { error, selectedMA, actorListTest2}
}//setup
}
</script>
这是 console.log(actorListTest1) 的输出:
然后这是 console.log(actorListTest2) 过滤后的输出:
这是一个 known problem with console.log
,它不应该用于实时调试对象值。
actorDocs
不是反应式的,在 Vue 中不能与异步操作一起正常工作。副作用应该在生命周期钩子中完成,例如:mounted
.
在当前状态下 getActorDocs
尚未准备好与组合 API 一起使用,因为它仅限于遵循承诺控制流以避免这种竞争情况:
onMounted(async () => {
await loadActors();
console.log(actorListTest2.value);
});
避免这种情况的正确方法是制作 actorDocs
反应数组或 ref:
const actorDocs = reactive([]);
如果需要在副作用中访问过滤值,例如console.log
,这是在观察者中完成的
const actorListTest2 = computed(() => actorDocs.filter(...));
watch(actorListTest2, v => console.log(v));
onMounted(() => {
loadActors();
});