原因
在父子组件传值时会遇到传的值是异步请求的数据,从而可能导致一些问题。父组件中发起请求拿到数据,将数据传给子组件,子组件onMounted生命周期却接收不到值(或者说只接收了父组件定义的初始值)。
主要是因为父子组件的生命周期:
加载渲染数据过程
vue2:父组件 beforeCreate -->父组件 created -->父组件 beforeMount -->子组件 beforeCreate -->子组件 created --子组件 beforeMount -->子组件 mounted -->父组件 mounted
vue3:子组件 onMounted -->父组件 onMounted
父组件:
<template>
<div id="app">
<Formation :current-project="currentProject" :origin-list="originList"></Formation>
</div>
</template>
<script lang="ts">
import Formation from "./view/Formation.vue";
import { onMounted } from "vue";
let currentProject=ref<any>()
// 用定时器模拟发请求异步获取后端接口的数据
setTimeout(() => {
currentProject = {
d_config:""
bd_live_time:0
bd_pos_status:0
command_format:""
create_time:1713492217292
describe:"dfdgb"
};
}, 200);
onMounted(() => {
console.log("父", currentProject);
});
</script>
子组件:
<template>
<div>
<h2>{{currentProject.describe}}</h2>
</div>
</template>
<script lang="ts">
import { onMounted} from "vue";
const props = defineProps({
currentProject: {
type: Object,
},
originList: {
type: Array<any>,
default() {
return [];
},
},
});
onMounted(() => {
console.log("子", props.currentProject);
});
</script>
结果:
方案一 使用v-if控制子组件渲染的时机
思路很简单,就是初始还没获取到异步数据的时候,不让组件渲染,等拿到的时候再渲染组件。通过v-if
控制子组件渲染,等拿到数据的时子组件就会渲染。可以认为是改变了父子组件的生命周期。但是这种方式有一个小问题,就是最终效果会显得子组件有些延迟才出现效果。因为异步数据是从后端的接口获取的,如果接口时间长一些的话,最终效果渲染也会慢一点。
父组件:
<template>
<div id="app">
<Formation v-if="isGetData" :current-project="currentProject" :origin-list="originList" ></Formation>
</div>
</template>
<script lang="ts">
import Formation from "./view/Formation.vue";
import {ref, onMounted } from "vue";
let currentProject=ref<any>()
let isGetData=ref(false)
// 用定时器模拟发请求异步获取后端接口的数据
setTimeout(() => {
currentProject = {
d_config:""
bd_live_time:0
bd_pos_status:0
command_format:""
create_time:1713492217292
describe:"dfdgb"
};
isGetData.value=true
}, 200);
onMounted(() => {
console.log("父", currentProject);
});
</script>
结果:
方案二 子组件使用watch监听父组件传递过来的数据
在子组件中监听父元素传过来的参数
子组件:
<template>
<div>
<h2>{{currentProject.describe}}</h2>
</div>
</template>
<script lang="ts">
import { onMounted,watch} from "vue";
const props = defineProps({
currentProject: {
type: Object,
},
originList: {
type: Array<any>,
default() {
return [];
},
},
});
watch(
() => props.currentProject,
(val, old) => {
console.log(val);//正常接收
}
);
</script>