这是Understanding Ember routes的后续内容。
主/详细视图很棒,但我试图在不嵌套模板的情况下使用分层 URL 路由。但是,对于面包屑链接和其他参考,我仍然需要访问父模型。
所以/users/1/posts
应该显示用户 1 的帖子列表。/users/1/posts/1
应该显示用户 1 的帖子 1,但它不应该在user
模板的{{outlet}}
. 相反,它应该完全替换user
模板。但是,我仍然需要访问post
模板中的当前用户,以便我可以链接回用户、显示用户名等。
首先我尝试了这样的事情(方法#1):
App.Router.map(function() {
this.resource('user', { path: '/users/:user_id' }, function() {
this.resource('posts', function() {
this.resource('post', { path: '/:post_id' });
});
});
});
...
App.PostRoute = Ember.Route.extend({
model: function(params) {
return App.Post.find(params.post_id);
},
renderTemplate: function() {
this.render('post', {
into: 'application'
});
}
});
正如预期的那样,这用模板替换了user
模板。post
但是当我单击浏览器的后退按钮时,user
模板不会再次呈现。显然 post 视图被破坏但父视图没有重新插入。这里有几个问题提到了这一点。
然后我让它与这样的东西一起工作(方法#2):
App.Router.map(function() {
this.resource('user', { path: '/users/:user_id' }, function() {
this.resource('posts');
this.resource('post', { path: '/users/:user_id/posts' }, function() {
this.resource('post.index', { path: '/:post_id' });
});
});
...
App.PostRoute = Ember.Route.extend({
model: function(params) {
return App.User.find(params.user_id);
},
setupController: function(controller, model) {
controller.set('user', model);
}
});
App.VideoIndexRoute = Ember.Route.extend({
model: function(params) {
return App.Post.find(params.post_id);
}
});
App.PostIndexController = Ember.ObjectController.extend({
needs: 'post'
});
但这对我来说似乎有点老套,而且不是很干。
首先,我需要在 中User
再次检索PostRoute
并将其作为临时变量添加到PostController
(如果路由正确嵌套并且我可以在 中设置一个needs: 'user'
属性,则不需要这样做PostController
)。此外,这可能会或可能不会对后端产生影响,具体取决于 ember-data 的适配器实现或用于从服务器检索数据的任何技术(即,它可能会导致不必要的第二次调用 load User
)。
我还需要一个额外的 `PostIndexController' 声明来添加新的依赖项,这没什么大不了的。
另一件感觉不对的事情是它/users/:user_id/posts
在路由器配置中出现了两次(一个嵌套,一个不嵌套)。
我可以处理这些问题并且它确实有效,但我想,总的来说,它似乎是被迫的,而不是那么优雅。我想知道我是否遗漏了一些明显的配置,可以让我使用常规嵌套路由执行此操作,或者是否有人建议使用更多“Ember.js 方式”来执行此操作。
我应该提一下,不管方法 #2 的技术优点如何,我都花了很长时间才弄清楚如何让它发挥作用。需要大量搜索、阅读、试验、调试等,才能找到正确的路由定义组合。我想这不是一个非常独特的用例,用户应该非常简单地设置这样的东西,而无需花费数小时的反复试验。如果最终是正确的方法,我很乐意在 Ember.js 文档中为此编写一些提示。
更新:
感谢@spullen 澄清这一点。我的案例不像示例那么简单,因为有些子路由需要嵌套模板而有些则不需要,但答案帮助我弄清楚了。我的最终实现看起来像这样:
App.Router.map(function() {
this.resource('users', { path: '/users/:user_id' }, function() {
this.resource('users.index', { path: '' }, function() {
this.resource('posts')
});
this.resource('post', { path: '/posts/:post_id' }, function() {
this.resource('comments', function() {
this.resource('comment', { path: '/:comment_id' });
});
});
});
});
所以现在在模板posts
下渲染但替换所有内容。然后渲染 under ,然后渲染 under 。users
post
comments
post
comment
comments
所有这些都是子路由,users
因此所有用户模型都可以在没有杂技的情况下访问,只需this.modelFor('users')
在需要的每个 Route 中执行即可。
所以模板看起来像这样:
users
|- posts
post
|- comments
|-comment
我不知道为什么资源定义{ path: '' }
需要users.index
它,但如果我把它拿出来,Ember 找不到users
路线。我很想摆脱最后的痕迹。