为什么props接收的值为undefined

在项目中,我们会经常使用到props传值,经常是由父组件传递给子组件一个值,然后我们在子组件中想去使用这个props接收的值,但是在created和mounted中打印,却发现是初始值或者为undefined,并不是我们在父组件中发送异步请求拿到的那个值.但是通过setTimeout设置了一定的时间之后,我们又能拿到对应的值.这是什么情况呢?

其中原因就是这样:因为父组件中的要就要传递的props属性 是通过发生ajax请求回来的, 请求的这个过程是需要时间的,但是子组件的渲染要快于ajax请求过程,所以此时 created 、mounted这样的只会执行一次的生命周期钩子,已经执行了,但是props还没有流进来(子组件),所以只能拿到默认值。

接下来,我们来跟着一个案例来解决这个问题吧.

案例的效果:在子组件中有一个previewUrl数据是预览的路径,他的路径是根据props传进来的值去赋值的,但是在created中直接赋值的话,previewUrl是为空.

解决:1.使用setTimeout(不推荐)。 缺点:原因是因为你不知道网络传输的具体时间有多久,直接写死一个值的话,容易有bug

<template>
  <div class="son">
    我是子组件
    <div>姓名:{{transData.name}}</div>
    <div>性别:{{transData.sex}}</div>
    <div>出年年纪:{{transData.birthDay}}</div>
    <div>图片路径:{{previewUrl}}</div>
  </div>
</template>

<script>
export default {
  props:{
    transData:{
      type:Object
    }
  },
  data(){
    return{
      previewUrl:''
    }
  },
  created(){
    this.previewUrl = this.transData.image
    // 直接打印打印不出来
    console.log(this.transData);
    setTimeout(()=>{
      // 能打印出来
      console.log(this.transData);
       this.previewUrl = this.transData.image
    },300)
  }
}
</script>

<style>

</style>

解决2.使用computed.缺点:只能用一个单独的值来,如果我这个previewUrl是在一个对象里面的话,就没办法了.

比如我是要赋值给imgSet对象中的 previewUrl。imgSet:{previewUrl: ‘’}这种,使用computed就不能很好的去赋值了。

<template>
  <div class="son">
    我是子组件
    <div>姓名:{{transData.name}}</div>
    <div>性别:{{transData.sex}}</div>
    <div>出年年纪:{{transData.birthDay}}</div>
    <div>图片路径:{{previewUrl}}</div>
  </div>
</template>

<script>
export default {
  props:{
    transData:{
      type:Object
    }
  },
  data(){
    return{
    }
  },
  computed:{
    previewUrl(){
      return this.transData.image
    }
  }
  // created(){
  //   this.previewUrl = this.transData.image
  //   // 直接打印打印不出来
  //   console.log(this.transData);
  //   setTimeout(()=>{
  //     // 能打印出来
  //     console.log(this.transData);
  //      this.previewUrl = this.transData.image
  //   },300)
  // }
}
</script>

<style>

</style>

解决3:使用watch。优点:即使是赋值给对象中的某个属性也可以很好的去赋值。

当然,有时候会监听不到,此时你可以去开启深度监听,就能监听的到了。此处就不多做展开了。

<template>
  <div class="son">
    我是子组件
    <div>姓名:{{transData.name}}</div>
    <div>性别:{{transData.sex}}</div>
    <div>出年年纪:{{transData.birthDay}}</div>
    <div>图片路径:{{previewUrl}}</div>
  </div>
</template>

<script>
export default {
  props:{
    transData:{
      type:Object
    }
  },
  data(){
    return{
      previewUrl:''
    }
  },
  watch:{
    'transData.image'(val){
      this.previewUrl = val
    }
  }
  // computed:{
  //   previewUrl(){
  //     return this.transData.image
  //   }
  // }
  // created(){
  //   this.previewUrl = this.transData.image
  //   // 直接打印打印不出来
  //   console.log(this.transData);
  //   setTimeout(()=>{
  //     // 能打印出来
  //     console.log(this.transData);
  //      this.previewUrl = this.transData.image
  //   },300)
  // }
}
</script>

<style>

</style>

解决4:使用v-if来判断,这样子在子组件中的created中就可以将有值的transData打印出来了。

缺点:如果业务复杂,传的值很多的话,那么我们每一个数据都需要在子组件标签上v-if,显得很乱

<son v-if="JSON.stringify(transData) !== '{}'" :transData="transData"></son>

参考地址:https://www.cnblogs.com/wmt-kilig/p/14015880.html

demo地址:https://github.com/rui-rui-an/propsIssue

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐