浅谈父子组件传值问题
作者:右眸Remnant
这篇文章主要介绍了Vue父子组件传值问题,文章中有详细的示例代码,感兴趣的同学可以参考阅读
一、问题描述
想要搭建一个模型检验的页面,在点击按钮“开始检测”后,后端会获取相应数据、页面跳转并进行渲染。
主要涉及三个页面: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>
运行结果如图,目前能够正常显示:
到此这篇关于浅谈父子组件传值问题的文章就介绍到这了,更多相关父子组件传值内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!