父子组件传值问题

Posted 右眸Remnant

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了父子组件传值问题相关的知识,希望对你有一定的参考价值。

文章目录


前言

在写毕业设计,涉及了一些前端Vue.js的组件传值知识并出现了相关问题,因此进行记录。

问题

  1. Vue.js的使用不熟练,相关组件、props等掌握不清晰
  2. 前端代码书写不规范

望指正!


一、问题描述

想要搭建一个模型检验的页面,在点击按钮“开始检测”后,后端会获取相应数据、页面跳转并进行渲染。
主要涉及三个页面:index.vue、BorderCard.vue、CardResult.vue,如图1:

index.vue想要引入“步骤条”实现两个组件的切换效果,如图2:

index.vue中引入两个组件的部分:

<border-card v-show="active === 0" :tab-index="active"/>
<card-result v-show="active === 1" />

相关部分代码如下:

// BorderCard.vue
<template>
<el-button style="position: absolute;top:-48px;right:20px;z-index: 999999;" @click="next">立即检测</el-button>
</template>
<script>
methods: 
	next() 
	  /** 点击立即检测按钮后,发送请求从后端获取数据(图表模型的正确率,数据信息等),然后利用 this.$emit -> 父组件 -> CardResult.vue
	  */
      console.log('handleModelTrain....');
      this.$http.post('').then(res => 
        console.log('handleModelTrain=>', res);
        this.$emit('next', res.data.data)
      ).catch(() => 
        this.$message.error('模型训练异常')
      )
    ,

</script>
// index.vue
<template>
<border-card v-show="active === 0" :tab-index="active" @next="handleNextTabs" />
<card-result v-show="active === 1" :model-report="modelReport" />
</template>
<script>
methods: 
	handleNextTabs(data) 
      console.log('recall=>', data);
      if (!data) 
        this.$message.error('模型训练异常')
      
      // 数据解析
      this.show_info.total = data.data_total
      this.modelReport = data
      if (this.active++ > 1) this.active = 0;
    ,

// CardResult.vue
<script>
props: 
    modelReport: 
      type: Object,
      default: () => 
        return 
          score: 0,
          report: ''
        
      
    
  ,
  watch: 
    modelReport: 
      handler: function(newVal, oldVal) 
        console.log('watch modelReport=>', newVal, oldVal);
        // 更新图表
        this.getEchartDataInit(false)
        // 更新表格
        this.getTableDataForReport(newVal)
      ,
      deep: true
    
  

单独呈现 CardResult.vue组件如图

当组件切换后,下面数据报告正常显示,但是图像发生了变形:

二、问题解决

查阅相关文章,其中原因包括:

  • 采用v-show控制切换时,v-show为false时,echarts图并不能获取外部容器的正常宽高,所以展示出来的图形会以其自身默认的大小展示;解决方法-> 在切换到图时重新调用图组件

根据上面说法,我理解的是切换组件的时候重新进行加载,相关博客建议使用组件 :key 属性,当发生变化后会重新加载组件,代码如下:

<border-card v-show="active === 0" :key="active" :tab-index="active" @next="handleNextTabs" />
<card-result v-show="active === 1" :key="!active" :model-report="modelReport" />

更改后的效果如图:

  • 此处组件传值失效的具体原因不清楚。是否和组件传值先被props接受,然后发生了组件重新加载有关

因此查找相关问题:Vue刷新后页面数据丢失问题的解决过程
解决方案:使用 SessionStorage 进行处理。
相关部分代码如下:

// index.vue
<script>
methods: 
    handleNextTabs(data) 
      console.log('recall=>', data);
      if (!data) 
        this.$message.error('模型训练异常')
      
      this.show_info.total = data.data_total
      this.modelReport = data
      // 将数据存储到sessionStorage
      sessionStorage.setItem('modelReport', JSON.stringify(this.modelReport))
      if (this.active++ > 1) this.active = 0;
    

</script>
// CardResult.vue
<script>
created() 
    console.log('CardResult created...');
    if (sessionStorage.getItem('modelReport')) 
      this.modelReport = sessionStorage.getItem('modelReport') // 获取数据直接更新
    
  ,
  beforeDestroy() 
    // 毁灭前先移除掉,否则我跳转到其它地方,sessionStorage里面依旧存在着
    console.log('CardResult beforeDestroy...');
    sessionStorage.removeItem('modelReport')
  

</script>

然而发生下列错误,如图:

为了避免直接改变prop中的值,因此我考虑继续使用 this.$emit -> index.vue,由于此时组件没有发生切换,因此不会触发组件的重新加载,然后实现赋值

修改后,部分相关代码如下:

// CardResult.vue
<script>
created() 
    console.log('CardResult created...');
    if (sessionStorage.getItem('modelReport')) 
      this.$emit('refreshData', JSON.parse(sessionStorage.getItem('modelReport')))
    
  ,
  beforeDestroy() 
    // 毁灭前先移除掉,否则我跳转到其它地方,sessionStorage里面依旧存在着
    console.log('CardResult beforeDestroy...');
    sessionStorage.removeItem('modelReport')
  

</script>
<template>
	<border-card v-show="active === 0" :key="active" :tab-index="active" @next="handleNextTabs" />
	<card-result v-show="active === 1" :key="!active" :model-report="modelReport" @refreshData="refreshDataParent" />
</template>
<script>
methods: 
	refreshDataParent(val) 
      console.log('refreshDataParent recall...');
      this.modelReport = val
    

</script>

运行结果如图,目前能够正常显示:


react 父子组件传值(兄弟传值)

参考技术A 父向子: 父组件通过自定义属性向子组件传值,子组件通过this.props.属性名接收
子向父: 子组件通过调用父组件以props传入的方法来更改父组件的数据

以上是关于父子组件传值问题的主要内容,如果未能解决你的问题,请参考以下文章

vue兄弟组件传值

459 vue使用$root$parent$children进行父子组件通信

VUe.js 父组件向子组件中传值及方法

非父子组件间的传值

vue ts ,vue使用typescript,三种组件传值方式

vue.js组件之j间的通讯一 子组件接受父祖件数据