Vue3 父子组件传值 日常开发中遇到一个问题(有点奇葩)

60 阅读2分钟

父组件

function autoCalc(tableData) {
    facilitiesCalculate(tableData).then(res => {
        if (res.code === 200) {
            tableData.value = [...res.data]
            isCalcTag.value = Math.floor(Math.random() * 100)
            ElMessage.success('操作成功')
        }
    })
}
<div class="right-box ">
                <component :is="currentComp" :tableData="tableData" :monthList="monthList" :activeFacility="isActive"
                    :isCalcTag="isCalcTag" @saveData="saveData" @autoCalc="autoCalc" />
            </div>

子组件

watch(
    () =>[prop.isCalcTag,prop.tableData], () => {
        getData() // 处理数组的方法
    },
  //() =>[prop.isCalcTag], () => {
  // 监听tabledata 不合适,页面卡顿,会消耗性能。于是就加了一个标识
      //  getData() // 处理数组的方法
    //},
)
function autoCalc() {
  // 提交到父组件。统一调用接口
    let arr = [...carbonObj.value.carbon_input.tableData, ...carbonObj.value.carbon_output.tableData, ...carbonObj.value.carbon_summary.tableData]
    emit("autoCalc", arr)
}

按照正常的思路和写法,这几串代码是完全没有问题的。既然提出来了,就肯定是有问题的。

问题描述:子组件获取的tabledata 数据还是旧数据,没有拿到父组件最新的数据。从autoCalc方法里面也是打印到最新的数据。

问题查找和解决:

  • 一开始从父子组件传值入手查,一直没有查出问题所在,在watch里面监听tabledata,发现只会在页面初始化时执行一次,后面就不在执行。
  • 又联想到可能是tabledata 里面有对象,对象里面套着数组,是嵌套太深的缘故。又尝试在watch 加上deep,结果还是跟之前一样
  • 再猜测是不是在子组件里面修改了tabledata,将所有关于tabledata的处理方法全部注释,因为console在控制台打印出来的信息不是准确的。处理完成之后发现问题还在。
  • 可能是其他子组件处理了tabledata,导致了数据的污染?
  • 开始重新定义一个变量t_tabledata,用于接收数据,父子组件传值。发现奏效了。问题解决了。

最后尝试的,发现是参数名跟自己定义的变量名是一样的,都是tabledata,将方法的参数名改为arr或者是其他的就可以。子组件也可以拿到最新的tabledata。

问题出现的底层原理还没有去了解。欢迎各位大佬来赐教