Bootstrap

vue3,父组件通过props传递异步数据,子组件接收不到问题

原因

在父子组件传值时会遇到传的值是异步请求的数据,从而可能导致一些问题。父组件中发起请求拿到数据,将数据传给子组件,子组件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>

;