Vue:道具未定义

时间:2020-10-30 15:39:36

标签: javascript vue.js google-cloud-firestore vuejs2 vue-props

我想将数据从父组件“ Product.vue”传递到子组件“ FavoriteButton.vue”。

在FavoriteButton.vue中,我在创建的挂钩中尝试了console.log(this.item),但所有值均未定义。

enter image description here

我可以将数据传递给其他子组件,例如Modal和MapProduct。

我不知道为什么无法将数据传递到FavoriteButton.vue。

我正在使用Firestore。 FavoriteButton.vue

<template>
    <div>
        <p><i v-if="fav" class="far fa-heart" @click.prevent="addFav(product)"></i></p>
        <p><i v-if="!fav" class="fas fa-heart" @click.prevent="deleteFav(product)"></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: {
                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
             }
             
          }
        },
        props: {
            productId: String,
            quantity: String,
            sale: String,
            business: String,
            address: String,
            uid: String,
            email: String,
            limitObject: String,
            limit: [String, Number]
        },
        computed: {
            
        },
        created() {
            
            fireApp.auth().onAuthStateChanged((user) => {
                if (user) {
                    console.log(this.item)
                    //const product = this.$route.params.id
                    const product = this.item
                    const userId = fireApp.auth().currentUser.uid;
                    const favoriteCollection = db.collection('Favorite').doc(userId).collection('FavoriteProducts').where("product_id", "==", product)
                    favoriteCollection.get().then((querySnapshot) => {
                    querySnapshot.forEach((doc) => {
                        if(doc.exists) {
                            this.fav = false
                        } else {
                            this.fav = true
                        }
                    })
                })
                } 
            });
        },    
        mounted() {
          
        },
        methods: {
          addFav(product) {
                this.$store.dispatch('createFav', product)
                this.fav = false
            },

        deleteFav(product) {
                this.$store.dispatch('deleteFav', product)
                this.fav = true
            },

        }

    }
</script>

Product.vue

<template>
    <div :class="{'is-open': modalOpen}">
        <Navbar />
        <div>
          <b-img class="image" type="" v-bind:src="sampleString" alt="image"></b-img>
          <div class="card__content">
              <div class="card__info">
                  <span class="text--medium">{{ data.business }}</span>
                  <!-- <span class="card__distance text--medium">{{ data.sale }}</span> -->
                  <span class="card__distance text--medium">{{ data.initial }}</span>
              </div>
          </div>
          <div class="left">
            <span>Only {{ data.quantity }}left!</span>
            
          </div>
          <div class="ex">
              <div class="time">
                <div class="closes_at">closes at</div>
              </div>
              <div class="time-number">
                <div class="time_at">{{ data.limitObject }}</div>
              </div>
          </div>
          <p class="description">{{ userData.description }}</p>
          <FavoriteButton 
          :productId="data.id"
          :quantity="data.quantity"
          :business="data.business"
          :address="data.address"
          :sale="data.sale"
          :uid="customer.uid"
          :email="customer.email"
          :limitObject="data.limitObject"
          v-bind:limit="data.limit"
          ></FavoriteButton>
          <b-button class="order-color" @click.prevent="showModal">Order</b-button><br>
          <!-- <b-button class="order-color" @click.prevent="favorite">Like</b-button> -->
          <p class="address">{{ data.address }}</p>
           <div class="spinner" v-if="loading">
              <spring-spinner
                      :animation-duration="3000"
                      :size="27"
                      color="#ff1d5e"
                      class="loading"
                  />
          </div>
          </div>
          <MapProduct 
         v-if="!loading"
      :latitude="latitudeString"
      :longitude="logitudeString"
      class="map-product"
          />
         
          <Modal 
          v-if="modalOpen" 
          :productId="data.id"
          :quantity="data.quantity"
          :business="data.business"
          :address="data.address"
          :sale="data.sale"
          :uid="customer.uid"
          :email="customer.email"
          :limitObject="data.limitObject"
          v-bind:limit="data.limit"
           />
          <!-- <b-modal v-model="modalShow">Hello From Modal!</b-modal> -->
         
    </div>
</template>

<script>
import Navbar from "@/components/Navbar.vue";
import Modal from "@/components/Modal.vue";
import MapProduct from "@/components/MapProduct.vue";
import FavoriteButton from "@/components/FavoriteButton.vue";
import { SpringSpinner } from 'epic-spinners'
import fireApp from '@/plugins/firebase'
const firebase = require("firebase");
require("firebase/firestore");
const db = firebase.firestore();

export default {
  name: 'Product',
  components: {
    Navbar,
    Modal,
    MapProduct,
    FavoriteButton
  },
  props: {
      src: String
  },
  data() {
      return {
        modalOpen: false,
        customer: "",
        data: "",
        userData: "",
        loading: false,
        sampleString: "",
        latitudeString: "",
        logitudeString: ""
      }
  },
  components: {
        SpringSpinner,
        MapProduct,
        Modal,
        Navbar,
        FavoriteButton
    },
    created() {
      fireApp.auth().onAuthStateChanged((user) => {
            if (user) {
                const user = firebase.auth().currentUser;
                this.customer = user
                //this.userInfo = user
            } 
        });

      let ref = db.collection('Product').doc(this.$route.params.id)
        ref.get()
        .then(snapshot => {  //DocSnapshot
              if (snapshot.exists) {
                  const product = snapshot.data()
                  this.data = product

                  const sample = snapshot.data().sample
                  const sampleString = sample.toString()
                  this.sampleString = sampleString

                  const latitude = snapshot.data().latitude
                  const latitudeString = latitude.toString()
                  this.latitudeString = latitudeString
                  
                  const longitude = snapshot.data().longitude
                  const logitudeString = longitude.toString()
                  this.logitudeString = logitudeString
                 
              } else {
                  console.log("No such document!");
              }  
        })

        this.loading = true
        let refUser = db.collection('ProUser').doc(this.$route.params.id)
        refUser.get()
        .then(snapshot => {  //DocSnapshot
              if (snapshot.exists) {
                  const proUser = snapshot.data()
                  this.userData = proUser
                  this.loading = false
              } else {
                  console.log("No such document!");
              }  
        })
    }, 
    mounted() {
      this.$store.commit('removeFromCart', this.item)
    },
    methods: {
      showModal() {
        this.modalOpen = !this.modalOpen
      },
      favorite() {
        //this.$store.commit('addToFavorite', this.item)
      }
    }
}
</script>

1 个答案:

答案 0 :(得分:0)

由于this.data是在Product.vue中异步获取的,因此当它最初作为FavoriteButton.vue传递到props时,它是不确定的。但是,您要将这些undefined值复制到本地item对象中,该对象不会响应prop值的更改。

我认为您需要为watch()中的每个道具添加FavoriteButton.vue并在this.item发生变化时进行更新(就像返回父项中的Promise一样) 。另外,您可以将this.item设为计算属性,但这取决于您要使用的属性。