同一个路由携带不同参数打开多个页面,多个页面的数据都一样(子组件实时监听父组件的属性变化,路由的传参未响应)

同一个路由携带不同参数打开页面,页面数据没有变化

一. 问题背景

嗯,又是满满的一天!话不多说,回到正题,这几天在做英语学习后台管理系统的时候,出现了一个问题,就是点击试卷详情(以下界面)
在这里插入图片描述进入试卷详情页查看该套试卷的用户学习记录(下图)
在这里插入图片描述在这里,我分别点开了三个不同试卷的学习记录,发现这三个记录都是相同的(一个吊样),这就让我懵逼了,咋回事?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述仔细看了一下地址栏,路由地址也不同撒。莫非是我的子组件接受父组件传过来的paperId的时候出问题了?这是我的第一个猜测。于是乎,我开始了我的bug分析之旅。

二. 问题分析

既然可能是父组件传过来的属性paperId没有及时被子组件实时接受,先转进代码界面看看。
这是子组件:
在这里插入图片描述在这里插入图片描述

这是父组件:
在这里插入图片描述嗯,父组件传值给子组件的方法没错,具体用法可以参考父子组件之间的传值
然后打开控制台看一下消息队列,看看打印出的paperId有没有变化:
在这里插入图片描述可以看到,打开第一个界面是有这个属性的,说明属性已经从父组件中传过来了,接着清空消息队列,打开第二个页面:
在这里插入图片描述好吧,页面没有变化,而且控制台也没有任何的log。但是,路由地址却出现了变化。这是咋回事?父组件的属性变化的时候,子组件的属性没有实时更新?还是说父组件的值其实是传过来了,然而子组件并没有及时的刷新(这是我的第二个猜测),于是我尝试的刷新了一下第二个试卷详情的页面,发现:
在这里插入图片描述
嘿哈,有东西了,然而不幸的事发生了,我跳到第一个试卷详情页面时,发现和第二页面同步刷新了,但是内容一毛一样:
在这里插入图片描述
不对啊,不应该每个页面的内容不一样吗?怎么又成了一样的?我本来还想着搞个刷新页面的方法,把当前页面直接刷一下就可以了呢。现在看来,这个问题没这么简单。嗯,先捋一下思路,父组件传值给子组件,但是多个子组件并不能同时分别获取到父组件的属性,只能同时共享一个属性值。艾玛,脑阔疼!等等,路由变化了,但是属性值并没有实时的传过来,不会是要我实时监听传过来的属性值变化吧!试一下加一下监听的代码:

watch: {
    paperId:{  
            handler:(val,oldval) => {  
            	console.log('val', val);
              	this.footShow = val;
            },  
            immediate:true,//关键
            deep:true
        }
  },

按照之前的步骤操作,嗯,还是空的:
在这里插入图片描述我快裂开了啊,到底是什么鬼嘛!冷静,冷静,项目肯定是要做下去的,只有冷静才能思考下去!好了,言归正传,继续分析。打开父组件的代码,也就是点击详情的时候,触发的方法,看看是不是传值的方法不对。

在这里插入图片描述
在这里插入图片描述
鉴于大家可能对这部分代码有点疑惑,直接看一下这个方法怎么用:编程式的导航(其实是我对这个知识也有点模糊了,捂脸笑,嘿嘿)。其实也就是通过这段代码导航到刚刚说的父组件Main,然后把参数传到父组件Main中,而父组件Main又包含三个子组件(注意:可能会和上文的父子组件有点混淆)
这是父组件(config):
在这里插入图片描述
这是子组件(Main),这是相对于config组件而言,但是相对于下面三个组件,这就是父组件,其传过来的paperId最终是要传给下面的子组件用的:
在这里插入图片描述
这才是最下层的子组件(三个):
在这里插入图片描述
config组件中通过触发编程式导航的方法(点击详细的按钮),跳转到Main组件所在的路由页面,并把paperId传了过来,但是Main组件又通过父子组件props传值的方式把paperId传给了三个子组件,三个子组件拿到这个paperId获取数据,并把数据展示出来。分析到这里,我好像明白了什么,每个试卷详情页面都是同一个路由,只不过携带的参数不同,既然同一个路由携带的参数不同,那么说明路由是由变化的,然而呢,子组件并没有响应路由携带的参数变化,所以导致了后面点击触发的组件页面并没有发生变化,又因为组件是复用的,导致了我一刷新一个页面,三个页面跟着刷新,变成和该页面一样的内容。当然我是这么认为的,如有不足之处,欢迎指正,但不接受批评!这回就要发挥我的百度大法了,嘿,还真给我搜到答案了。
在这里插入图片描述

若要对路由参数的变化作出响应的话,就需要在此组件上使用 watch(监测变化) $route 对象。作为一个合格的前端入门小白,遇到不懂的,先看官方文档: $route
vue-router

虽然我觉得官方文档写也挺模糊的。至少原理给你讲了,就是通过$route使用一个 watcher 去响应路由的改变。
好了,既然找到解决方案就先试一下呗:
在这里插入图片描述
to表示这个子组件所在的路由,也就是父组件去往的路由(子路由),比如当点击详情按钮的时候,会跳转到下面这个路由:

在这里插入图片描述
from表示的是从哪个路由跳转过来的(跳转这个子路由的上一个路由),就是出现详情按钮 的哪个界面所在的路由:
在这里插入图片描述
paperId这个参数又是以放在query中的方式传过来的,所以要带上to.query.paperId
在这里插入图片描述
当然还要判断一下有没有paperId传过来或者传过来的paperId是不是和现在用的这个paperId一样,因为组件的复用性,会导致组件的同时刷新,所以,我们刚好可以通过这种方式保证其他的组件不会被一起响应刷新,又可以对这个变化的paperId进行重新赋值,变相的只刷新了这个组件页面,岂不美哉!昂,调试了一下,终于解决了,加油,踩坑越多,越牛逼!

三. 总结

与其说是父子组件之间的传值导致页面数据不刷新的问题,倒不如说是组件未监听到路由的传参, 导致组件未响应路由的传参,而无法实现每个组件页面数据的传值的问题!
好了今天的博文到此结束,下次再见!嘿哈!

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值