使用 vue-router,页面加载完成后,$route 的值不正确

1 问题描述

页面加载时,需要判断:地址能否匹配上路由。如果匹配不上,就跳转到首页。

代码:

mounted(){
	if (this.$route.matched.length === 0) {
		this.$router.push("/index");
	}
}

问题出现了:当访问的地址可以匹配上路由时,也会跳到首页。


2 找到问题

在 mounted 中打印 $route
在这里插入图片描述
可以看到,所有的值都不对。最明显的是pathfullPath ,明明应该有值,但现在只是一个 "/"

我猜测:在 mounted 中,router 的初始化还没有完成,所以取到的是一个初始默认值。

加一个延时,试一下:

mounted(){	
	setTimeout(() => {
		if (this.$route.matched.length === 0) {
			this.$router.push("/index");
		}
	},1000);
}

延时 1000ms ,此时router 的值是对的了:
在这里插入图片描述
问题确定了:

  • vue-router 初始化是需要一段时间的,在完成之前,取值只能拿到初始的默认值。
  • 在 mounted 中 router 初始化可能还没有完成。

3 不能用定时器,用 onReady

上面用定时器延迟了1000ms,取到了 router。但是,真正要解决这个问题,肯定不能用定时器,因为延迟的时间无法确定:

  • 长了,影响体验
  • 短了,可能router初始化还没完成呢

我去翻了官网API,希望官方提供了初始化完成时的回调方法,果然找到了:onReady

代码改成:

mounted(){	
	this.$router.onReady(() => {
		if (this.$route.matched.length === 0) {
			this.$router.push("/index");
		}
	});
}

完美通过!


4 有的同学可能会担心:onReady会不会错过啊?

(可能只有我担心这个问题)

4.1 “错过”是什么意思

先解释一下 “错过”。举个例子:

给 window 绑定 load 事件:

<!DOCTYPE html>
<html>
<head>
	<script>
		window.onload = function() {
			alert("load")
		};
	</script>
</head>
<body></body>
</html>

会弹出:
在这里插入图片描述

如果延迟一会儿,再绑定事件呢:

<!DOCTYPE html>
<html>
<head>
	<script>
		setTimeout(() => {
			window.onload = function() {
				alert("load")
			};
		}, 2000);
	</script>
</head>
<body></body>
</html>

这样就不会弹出了。因为延迟了2000ms 后才绑定事件。这个时候 window已经 load 完了。错过了。

4.2 onReady会不会"错过"呢?

先说结论:不会!

因为 window.onload 和 vue-router 的 onReady 是完全不同的两种机制:

// 机制一:绑定处理函数。绑定好之后,window触发load事件时,才会调用。所以存在错过的现象
window.onload = cb;

// 机制二:调用 onReady 函数!
router.onReady(cb); 

去看看 源码 ,onReady 到底是做了什么:
在这里插入图片描述
onReady:

  • 如果路由已经 ready 了,就立即执行 cb
  • 如果路由还没有 ready,就把 cb 放到 readyCbs 中。

接着看源码,发现:
在这里插入图片描述
上面这段代码是在初始化完成后立即调用的:修改 ready 为 true ,并执行 readyCbs 中的 cb 。

所以,onReady不会错过,放心的用!


参考:

发布了13 篇原创文章 · 获赞 13 · 访问量 4500

猜你喜欢

转载自blog.csdn.net/tangran0526/article/details/104038123