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

Vue3中组件向视图传递tmp_sell变量失败问题求助

问题分析与修复方案

核心问题点

  1. 事件名完全不匹配:子组件发射的事件名是choosenOneProduct,但父组件监听的是choosen_products和tmp_sell,两者毫无对应,导致tmp_sell无法传递到父组件。
  2. 同名变量冲突:子组件同时在props和data中声明choosen_products、tmp_sell,违反Vue单向数据流规则,造成变量逻辑混乱。
  3. 同一事件名重复发射不同数据:子组件两次调用$root.$emit('choosenOneProduct', ...),分别传递数组和数值,即使父组件监听该事件,也无法区分两种数据。
  4. 父组件误用props接收子组件数据:tmp_sell是子向父传递的数据,父组件应在data中定义变量存储,而非声明为props(props是父传子的通道)。
  5. 未利用Vue响应式绑定输入框:父组件打算用DOM操作赋值input,不符合Vue响应式思路,应使用v-model实现自动更新。

修复后的代码

1. AllProductsChoose.vue(子组件)

<template>
  <tr class="choose_product" v-for="p, i in all_products" :key="i" @click.prevent="choosenOneProduct(p, i)">
    <!-- 累计所选商品的p_sell值 -->
    <td>{{ p.p_sell }}</td>
    <td>
      <div>
        <button class="btn btn-info" @click.prevent="choosenOneProduct(p, i)"> [+] </button>
      </div>
    </td>
  </tr>
</template>

<script>
export default {
  name: 'all-products-choose',
  // 移除props中与data同名的变量,内部状态由data维护
  data() {
    return {
      choosen_products: [],
      tmp_sell: 0
    }
  },
  methods: {
    choosenOneProduct(p, i) {
      const choose_product_ref = firebase.firestore().collection("all_products").where("p_fullname", "==", p.p_fullname);
      choose_product_ref.onSnapshot((snapshot) => {
        snapshot.docs.forEach(d => {
          const product = d.data();
          const tmp_one_sell = parseFloat(d.data().p_sell);   
          this.tmp_sell += tmp_one_sell;
          this.choosen_products.push(product);
          
          // 发射不同名称的事件,分别传递两类数据
          this.$emit('update:choosen-products', this.choosen_products);
          this.$emit('update:tmp-sell', this.tmp_sell);
        })
      })
    }
  }
}
</script>

2. 父视图组件

<template>
  <all-products-choose 
    @update:choosen-products="getChoosenProducts"  
    @update:tmp-sell="getTmpSell"
  ></all-products-choose>

  <!-- 用v-model.number绑定响应式变量,实现输入框自动更新 -->
  <input type="number" v-model.number="tmp_sell" placeholder="Subtotal" id="q_subtotal" />
</template>

<script>
import AllProductsChoose from './AllProductsChoose.vue';

export default {
  components: {
    AllProductsChoose
  },
  data() {
    return {
      choosen_products: [],
      tmp_sell: 0
    }
  },
  methods: {
    getChoosenProducts(products) {
      this.choosen_products = products;
    },
    getTmpSell(sell) {
      this.tmp_sell = sell;
    }
  }
}
</script>

额外优化建议

  • 避免使用$root.$emit,直接用组件自身的$emit,遵循组件间通信的标准方式。
  • 给v-for添加:key属性,提升渲染性能并消除Vue警告。
  • 可考虑用Vue3组合式API(setup语法糖)重构代码,更贴合Vue3开发习惯。

内容的提问来源于stack exchange,提问作者ZION WONG

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 03:23:33