复现问题

为了方便我直接在main.js中使用mockjs模拟一个接口请求并为其设置了2秒的响应时间

mian.js

import Vue from "vue";
import App from "./App.vue";

const Mock = require("mockjs");
// 请求的响应时间2秒
Mock.setup({
    timeout: "2000",
});

// 请求方式要使用小写
Mock.mock("/test", "get", {
    "msg|1-10": "★",
});

Vue.config.productionTip = false;

new Vue({
    render: (h) => h(App),
}).$mount("#app");
父组件中将自己的msg传递给子组件,父组件中的msg来自于接口异步任务。

父组件

<template>
  <div>
    <HelloWorld :msg="msg" />
  </div>
</template>

<script>
import HelloWorld from "./components/HelloWorld.vue";
import axios from "axios";
export default {
  name: "App",
  data() {
    return {
      msg: "默认值",
    };
  },
  components: {
    HelloWorld,
  },
  created() {
    axios({
      method: "get",
      url: "/test",
    }).then(response => {
      console.log(response, "response");
      this.msg = response.data.msg;
    });
  },
};
</script>

<style></style>

子组件接收msg并展示

子组件

<template>
  <div>{{ msg }}</div>
</template>

<script>
export default {
  name: "HelloWorld",
  props: {
    msg: String,
  },
  data() {
    return {
      msgSon: this.msg,
    };
  },
  mounted(){
    setInterval(() =>{
      console.log(this.msgSon)
    },1000)
  }
};
</script>

<style scoped></style>

运行效果
在这里插入图片描述

一开始输出“默认值”没错,但是我们发现接口返回之后,父组件的msg已经修改了,但是
子组件还是一直输出“默认值”。

分析原因

因为把props的值赋值给data不是响应式的,props中的值改变了,data中的值不会
响应式更改。回到我们的文章标题:data中获取不到props中的值,可能大家在父组件
中设置的值为undefined,但是大家又觉得我明明在接口响应中给它赋值了,所以大家
觉得是子组件props没有获取到值什么的,其实只是因为在子组件渲染的时候,props
会去父组件中获取值,但是父组件此时的值在接口中还没有返回,所以只是默认值。

解决方案

使用watch

站在子组件的角度思考:不就是父组件值改了,但是我子组件不知道嘛,没关系,vue为
我们提供了watch,可以监听一个值是否变化,我用watch监听你父组件传给我的值,你一
旦改了值,我就把我的data中复制出来的值也改了不就行了。
<template>
  <div>{{ msg }}</div>
</template>

<script>
export default {
  name: "HelloWorld",
  props: {
    msg: String,
  },
  data() {
    return {
      msgSon: this.msg,
    };
  },
  mounted() {
    setInterval(() => {
      console.log(this.msgSon);
    }, 1000);
  },
  watch: {
    msg: function (newVal) {
      this.msgSon = newVal;
    },
  },
};
</script>

<style scoped></style>

运行效果
在这里插入图片描述

使用v-if

站在子组件的角度思考:我渲染的时候需要拿值,但是你父组件还没有拿到真正的值,那
我就先不渲染呗,等你拿到真正的值了,再让我渲染,此时我拿到的值不就是真正的值了。
<template>
  <div>
    <HelloWorld :msg="msg" v-if="lock"/>
  </div>
</template>

<script>
import HelloWorld from "./components/HelloWorld.vue";
import axios from "axios";
export default {
  name: "App",
  data() {
    return {
      msg: "默认值",
      lock: false,
    };
  },
  components: {
    HelloWorld,
  },
  created() {
    axios({
      method: "get",
      url: "/test",
    }).then(response => {
      console.log(response, "response");
      this.msg = response.data.msg;
      this.lock = true;
    });
  },
};
</script>

<style></style>

运行效果
在这里插入图片描述

Logo

前往低代码交流专区

更多推荐