You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue父子组件传值异常:FavoriteButton.vue接收Props为undefined

解决Vue父子组件传值时子组件created钩子中props未初始化的问题

我看了你遇到的问题:父组件Product.vue给FavoriteButton.vue传值,但子组件created里打印this.item全是undefined,其他子组件却正常。这问题其实是Vue组件生命周期的小坑,我帮你梳理下原因和解决办法:

问题根源

你在FavoriteButton.vue的data里直接用this.productId这类props去初始化item对象,但Vue组件的props是在实例创建完成后(created钩子之前的阶段)才被注入到实例中的,而data的初始化是在更早的阶段(beforeCreate之后、created之前),这时候props还没赋值,所以item里的所有属性自然都是undefined。

而其他子组件(比如Modal、MapProduct)没问题,大概率是它们没有在这么早的阶段就直接依赖props初始化数据,而是在模板里直接使用props,或者在mounted之后才使用,这时候props已经完全初始化了。

解决方案

1. 把item改成计算属性(推荐)

计算属性会自动响应props的变化,而且能确保你拿到的是最新的props值,完全避免初始化时机的问题:

修改FavoriteButton.vue的代码:

<template>
  <div>
    <p><i v-if="fav" class="far fa-heart" @click.prevent="addFav"></i></p>
    <p><i v-if="!fav" class="fas fa-heart" @click.prevent="deleteFav"></i></p>
  </div>
</template>

<script>
import fireApp from '@/plugins/firebase'
const firebase = require("firebase");
require("firebase/firestore");
const db = firebase.firestore();
import store from '../store'
import { mapGetters } from 'vuex'

export default {
  name: "FavoriteButton",
  data() {
    return {
      fav: true
      // 删掉原来的item定义
    }
  },
  props: {
    productId: String,
    quantity: String,
    sale: String,
    business: String,
    address: String,
    uid: String,
    email: String,
    limitObject: String,
    limit: [String, Number]
    // 注意:你定义了numberOfOrders和count,但父组件没传,这两个会一直是undefined,记得补传或者删掉
  },
  computed: {
    // 用计算属性生成item
    item() {
      return {
        productId: this.productId,
        numberOfOrders: this.numberOfOrders, // 父组件未传递,需确认是否需要
        uid: this.uid,
        email: this.email,
        sale: this.sale,
        business: this.business,
        address: this.address,
        limitObject: this.limitObject,
        limit: this.limit,
        count: this.count // 父组件未传递,需确认是否需要
      }
    }
  },
  created() {
    fireApp.auth().onAuthStateChanged((user) => {
      if (user) {
        console.log(this.item); // 现在能拿到正确的值了
        // 注意:你原来的查询用this.item作为product_id的匹配值,应该是用productId吧?
        const product = this.item.productId;
        const userId = fireApp.auth().currentUser.uid;
        const favoriteCollection = db.collection('Favorite').doc(userId).collection('FavoriteProducts').where("product_id", "==", product);
        
        favoriteCollection.get().then((querySnapshot) => {
          // 优化判断逻辑:只要有查询结果,就说明已收藏
          this.fav = querySnapshot.size === 0;
          // 等价于你原来的逻辑:有doc存在则fav=false,否则fav=true
        })
      }
    });
  },
  methods: {
    addFav() {
      this.$store.dispatch('createFav', this.item) // 这里也换成this.item
      this.fav = false
    },
    deleteFav() {
      this.$store.dispatch('deleteFav', this.item) // 换成this.item
      this.fav = true
    },
  }
}
</script>

2. 若要保留data,则在created中赋值

如果你不想用计算属性,也可以在created钩子中给item赋值,这时候props已经注入完成了:

data() {
  return {
    fav: true,
    item: {} // 先初始化空对象
  }
},
created() {
  // 先给item赋值
  this.item = {
    productId: this.productId,
    uid: this.uid,
    email: this.email,
    sale: this.sale,
    business: this.business,
    address: this.address,
    limitObject: this.limitObject,
    limit: this.limit
  };
  // 再执行Firestore逻辑
  fireApp.auth().onAuthStateChanged((user) => {
    // ...后续代码
  })
}

额外注意点

  • 你子组件定义的numberOfOrders和count两个props,父组件Product.vue并没有传递,这两个值会一直是undefined,记得要么在父组件补传,要么删掉这两个没用的props。
  • 原来的Firestore查询遍历querySnapshot的逻辑可以优化,直接用querySnapshot.size判断是否有收藏记录,避免多次修改fav值的问题。

内容的提问来源于stack exchange,提问作者Yohei Umezu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 17:37:36