Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

带有watch $route时每次进来都会执行两次 #60

Open
louisscrew opened this issue Oct 10, 2018 · 9 comments
Open

带有watch $route时每次进来都会执行两次 #60

louisscrew opened this issue Oct 10, 2018 · 9 comments

Comments

@louisscrew
Copy link

问题很有意思
场景如下:
页面A和页面B
页面B中有如下代码:

module.exports = {
   ...
  watch: {
		'$route': function (nv) {
			if (nv.name === "talk") {
				this.initData();
			}else{
				this.closeTalk();
			}
		}
	},

}

页面B带有参数,根据不同的参数获取数据,因此加了一个watch $route的监听。

问题来了,
第一次从页面A到页面B时,执行正常。但是在从页面B使用router.push的方式回到页面A后,再从页面A进入页面B时,watch监听方法执行了两次,重复上述操作几次,watch就会重复监听几次。

但是如果通过页面B使用浏览器的回退到页面A后,再从页面A进入到页面B,watch就不会重复。

但不是用这个插件后,所述watch重复问题不在发生。

@zack24q
Copy link
Owner

zack24q commented Oct 10, 2018

我觉得可能是这样的:A->B,然后你使用的是router.push,所以不会返回到原来的A页面,而是打开新的A页面,然后又到了B,同理打开的是新的B页面,所以就会有多次的watch触发情况,B在内存中,并没有被销毁。
如果希望B返回A,不应该使用push

@louisscrew
Copy link
Author

你分析的有道理,但是无论如何都无法避免这样的事情。
比如页面有三个,A、B、C
从A进入到B,在从B进入到了C,C中提供了一个回到首页的链接,使用push的方式会到A。这样再从A到B时也同样有这个问题。
总不能在C中执行两次返回到A吧。

@zack24q
Copy link
Owner

zack24q commented Oct 10, 2018

这种情况使用原生的api就可以解决了,一次返回多层历史记录,history.go(-2)文档地址

@louisscrew
Copy link
Author

god
我只是举了一个例子,在实际的例子中有可能会有很多页面的。
而且页面中都有可能跳转到其他页面。页面之间的跳转是用户随性的并不会按照我们设定的逻辑执行,因此history.go()返回到第几步是未知的。比如
A->B->C->D->B->D->C->B,每一个箭头都push进入的。主要是push进入到B,watch就会重复。

具体的实例手机版本淘宝:
从首页->搜索->进入一个商品详细->在从商品相信进入到另一个商品详细->进入店铺页面->进入购物车。。。。。

手机淘宝处了首页其他页面几乎右上角的...中都带有一个返回主页的按钮。这个按钮不会是history.go返回第几层的。

@zack24q
Copy link
Owner

zack24q commented Oct 10, 2018

这种情况可能是不该使用watch的,watch加了一个监听,但是跳转页面后并没有释放掉,所以每次创建新页面,就会多一个watch了;类似addEventLinstener,需要在生命周期钩子里来把监听释放掉,或者把监听中心化,不放在页面里,放在类似vuex之类的地方去管理
我们可以再讨论一下有没有更好的解决方案;组件需要缓存,但是watch监听不要触发,这个其实是矛盾的

@louisscrew
Copy link
Author

之所以要用watch是在同一个页面b上会根据参数的不同加载数据。比如用户页面,在这个用户页面还会有其他的用户的链接。点击这个链接时要切换用户数据。但是组件是一个,只是参数不同。我就通过watch监控$route来实现。

vue有注销和销毁watch的途径吗?请赐教。

@zack24q
Copy link
Owner

zack24q commented Oct 10, 2018

有的,官方的方法 文档地址

@zealot09
Copy link

我觉得解决这个问题的根本途径不是 监听$route的参数,而是将每次路由的参数包括相应路由后续的数据 存储到store里去,store也按照vue instance规则,按照路由的key (history.state.key) 隔离起来。

相应Vue instance里只监听该instance 对应的store,这才是通用的方案。

上面提到的条件性的 $watch 方案不够通用,还是要根据业务形态调整代码。最近也在思考这方面的实现,头疼

@fqniu
Copy link

fqniu commented Sep 15, 2021

也遇到这种情况,每次切换路由,会多次执行watch里面监听的$route,想问一下讨论的怎么样了呢

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants