router.js配置疑问:访问dashboard/posts/id/comments报UnrecognizedUrl错误
首先,你最初的路由配置触发UnrecognizedUrl错误的原因很明确:子路由的path配置重复继承了父路由的参数。
你的第一版代码里,comments是show路由的子路由,而show已经定义了path: ':post_id'。当你给comments设置path: ':post_id/comments'时,Ember会自动拼接父路由的路径前缀,最终生成的实际路由路径会变成:
dashboard/posts/:post_id/:post_id/comments
重复的:post_id参数完全不符合预期的URL结构,自然会导致URL解析失败。
方案1:嵌套结构下的正确URL(在show页面的outlet中显示comments)
如果你希望comments内容仍然嵌套在show页面的{{outlet}}里,同时URL为dashboard/posts/id/comments,你的第二版配置已经接近正确,只需要给comments路由补全正确的path即可:
this.route('dashboard', function() { this.route('posts', function() { this.route('show', { path: ':post_id' }, function() { // 子路由的path写相对路径即可,父路由的:post_id会自动继承 this.route('comments', { path: 'comments' }); }); }); });
这样生成的URL就是dashboard/posts/:post_id/comments,同时comments模板会正常渲染在show页面的{{outlet}}中,和你之前测试的有效效果一致。
方案2:独立页面的comments路由(不嵌套在show页面)
如果你的需求是让comments作为完全独立的页面(不需要依赖show页面的{{outlet}}),那需要调整路由层级,把comments作为posts的直接子路由,而非show的子路由:
this.route('dashboard', function() { this.route('posts', function() { this.route('show', { path: ':post_id' }); // 将comments作为posts的直接子路由,指定完整相对路径 this.route('comments', { path: ':post_id/comments' }); }); });
这种配置下,dashboard/posts/:post_id/comments会对应一个独立路由,它的模板会作为完整页面渲染,不需要嵌套在其他页面中。不过要注意,你需要把原来show/comments目录下的模板和逻辑代码,移动到posts/comments目录下,或者通过路由的route属性指定对应文件位置。
总结一下核心要点:
- 嵌套路由的
path是相对父路由的,不要重复父路由已经定义的参数 - 想要嵌套显示就把
comments设为show的子路由,指定path: 'comments' - 想要独立页面就把
comments设为posts的子路由,指定path: ':post_id/comments'
内容的提问来源于stack exchange,提问作者Mikelemuel

