AngularJS ui-router状态匹配异常:Schedule链接加载page状态修复咨询
解决AngularJS ui-router状态匹配冲突的问题
嘿,我之前也碰到过ui-router 0.x版本的这种路由匹配坑,让我帮你理清楚问题所在和解决办法:
问题到底出在哪?
你用的是ui-router v0.2.18,这个版本的路由匹配逻辑是按你定义状态的顺序来的,谁先定义就优先匹配谁。再看你的两个状态URL:
page状态的URL是/:pageId/:pageType,它会匹配任何两段式的路径——比如你访问的/Schedule/691d6981b8dd47e0a158d67cb02b1fee/,会被它当成pageId=Schedule、pageType=那个长ID,直接匹配上了。schedule状态的URL是/Schedule/:scheduleId/:pageId/:pageType,但你设置了pageId和pageType的squash: true,当这两个参数为空时,URL会简化成/Schedule/:scheduleId/,刚好符合page状态的两段式规则,所以只要page状态定义在前面,就会被优先触发。
三个靠谱的修复方案
方案1:调整状态定义顺序(最快见效)
把schedule状态的代码放在page状态前面,这样ui-router会先检查路径是否符合/Schedule/...的格式,只有不匹配的时候才会去触发page状态:
$stateProvider // 先定义schedule状态 .state("schedule", { url: "/Schedule/:scheduleId/:pageId/:pageType", template: pageTemplate, controller: "contentCtrl", resolve: { ... }, params: { pageId: { squash: true, value: null}, pageType: { squash: true, value: null}, reload:true } }) // 再定义page状态 .state("page", { url: "/:pageId/:pageType", template: pageTemplate, controller: "contentCtrl", resolve: { ... }, params: {reload: true} });
方案2:给page状态加唯一URL前缀(最稳妥的长期方案)
直接修改page状态的URL,加个专属前缀比如/page/,彻底避免和schedule的URL冲突:
$stateProvider .state("page", { url: "/page/:pageId/:pageType", // 加个/page/前缀 template: pageTemplate, controller: "contentCtrl", resolve: { ... }, params: {reload: true} }) .state("schedule", { url: "/Schedule/:scheduleId/:pageId/:pageType", template: pageTemplate, controller: "contentCtrl", resolve: { ... }, params: { pageId: { squash: true, value: null}, pageType: { squash: true, value: null}, reload:true } });
这样page状态只会响应/page/xxx/yyy这种格式的路径,再也不会和/Schedule/xxx/搞混了。
方案3:给page状态的参数加正则约束(精细控制)
如果不想改URL结构,可以给page状态的pageId参数加个正则,让它不能匹配Schedule这个值:
$stateProvider .state("page", { url: "/:pageId/:pageType", template: pageTemplate, controller: "contentCtrl", resolve: { ... }, params: { pageId: { regex: /^(?!Schedule$).+/ }, // 排除pageId等于Schedule的情况 reload: true } }) .state("schedule", { url: "/Schedule/:scheduleId/:pageId/:pageType", template: pageTemplate, controller: "contentCtrl", resolve: { ... }, params: { pageId: { squash: true, value: null}, pageType: { squash: true, value: null}, reload:true } });
这个正则的意思是:匹配任何不是Schedule的字符串,这样当路径以/Schedule/开头时,就不会被page状态误匹配了。
额外小建议
ui-router v0.2.18确实有点老了,如果项目允许的话,建议升级到ui-router 1.x版本,它的路由匹配逻辑更智能,是基于状态树和优先级的,能更好地处理这类冲突,还多了不少实用特性。
内容的提问来源于stack exchange,提问作者Bogdan
相关产品推荐
相关产品推荐

