场景
当我将父组件从服务端异步获取的数据传给子组件的时候,子组件里面显示不了对象的属性
代码:
父组件:NewsView
<template>
<div class="home">
<h1>好文精选</h1>
<News :item="newsArray[1]"></News>
</div>
</template>
<script lang="ts" setup>
import { IArticle } from "@/types"
import { onBeforeMount, ref } from "vue"
import { news } from "../services/api"
import News from "../components/News.vue"
let newsArray = ref<IArticle[]>([])
onBeforeMount(async () => {
try {
let res = await news()
if (res.stat === "OK") {
newsArray.value = res.rows
}
} catch (error) {
console.log(error)
console.log("服务器错误")
}
})
</script>
子组件:News
<template>
<div>
<div>{{ item.title }}</div>
<div>{{ item.author }}</div>
</div>
</template>
<script lang="ts" setup>
import { IArticle } from "../types"
import { defineProps, onBeforeMount } from "vue"
const props = defineProps<{
item: IArticle
}>()
onBeforeMount(() => {
console.log(props)
})
</script>
<style lang="scss" scoped></style>
结果:
问题
根据上述结果得出问题:
- 页面显示不出数据:报错
- 当你的父组件传给子组件的数据为异步向服务端请求的数据时,子组件刚开始打印出来的为空值,后来才是正确的值
原因
针对页面上显示不出来数据
,是因为没有传递过来的对象,默认是一个空对象,里面没有属性
针对props刚开始获取的为undefined
(观察结果图,发现控制台输出了两次props中获取的数据,第一次item为undefined,第二次就是正确的值),这是因为异步向服务器请求数据,数据还没来之前,子组件已经渲染到了页面上,里面item的值就是默认值,也就是undefined
解决办法
针对页面的显示
,我们只需要给item附上默认值即可
针对js代码中获取到的数据为undefined
,我们使用监听即可,对props中的item进行监听,如果有值了就可以进行后续操作
代码:
<template>
<div>
<div>{{ item.title }}</div>
<div>{{ item.author }}</div>
<hr />
</div>
</template>
<script lang="ts" setup>
import { IArticle } from "../types"
import { defineProps, onBeforeMount, watch, withDefaults } from "vue"
// 设置默认值
const props = withDefaults(
defineProps<{
item: IArticle
}>(),
{
item: () => {
return { id: "", title: "", time: "", avatar: "", author: "", banner: "", likes: 0, comments: 0, content: "" }
},
}
)
// 使用监听来获取异步后面响应回来的数据
watch(
() => props.item,
(val, preval) => {
console.log(val)
},
{
immediate: true,
deep: true,
}
)
</script>
<style lang="scss" scoped></style>
注意:如果是遍历数组,生成子组件的话,就不会有这个问题,因为v-for是异步的,前提是数组里有值才能遍历生成子组件,所以生成子组件的时候一定是传递了正确的数据过去的