UI5中attachRoutePatternMatched等路由监听单次导航多次触发问题问询
问题原因解析
- 核心原因是全局路由监听器重复绑定
你所有业务视图的控制器都继承自BaseController,而UI5中每个控制器实例化时都会执行一次自身的onInit生命周期方法,所以每初始化一个视图控制器,都会给全局唯一的Router实例新增一个attachRoutePatternMatched监听回调。这些回调会持续存在直到Router销毁/手动解绑,因此你实例化了多少个继承BaseController的控制器,单次路由匹配就会触发多少次onViewSwitch方法,你遇到的触发5次的情况正好对应你此时已经实例化了5个业务控制器。 - 为什么指定单个路由的
attachMatched依然会多次触发
不管是全局的路由匹配事件还是单个路由的匹配事件,绑定逻辑都是一致的:你在BaseController中注册多少次,事件触发时就会执行多少次回调,和你是否指定具体路由没有关系,只要重复绑定就会重复触发。 - 为什么移到rootView控制器后问题解决
整个应用的根视图控制器在应用生命周期内只会实例化一次,对应的onInit方法仅执行一次,只会注册一个路由监听回调,因此单次路由匹配只会触发一次onViewSwitch。
可选优化方案(如果仍希望在BaseController中实现该逻辑)
- 方案1:全局标记控制仅绑定一次
可以在OwnerComponent上增加标记位,控制全局仅注册一次监听:
onInit() { const ownerComp = this.getOwnerComponent(); // 已经绑定过则直接返回 if (ownerComp.__isRouteListenerAttached) return; const router = ownerComp.getRouter(); router.attachRoutePatternMatched((event) => { this.onViewSwitch(event); }, this); // 打标记避免重复绑定 ownerComp.__isRouteListenerAttached = true; }
- 方案2:控制器销毁时同步解绑监听
绑定监听器时存储回调引用,在控制器onExit生命周期中手动解绑,避免监听器累计:
onInit() { const router = this.getOwnerComponent().getRouter(); // 存储回调引用用于后续解绑 this._routeMatchHandler = (event) => { this.onViewSwitch(event); }; router.attachRoutePatternMatched(this._routeMatchHandler, this); }, onExit() { const router = this.getOwnerComponent().getRouter(); router.detachRoutePatternMatched(this._routeMatchHandler, this); delete this._routeMatchHandler; }
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

