JavaScript 请教关于 Ember.js 中如何把 Nested Routes 加载到同一个模板的问题

aidewoode · 2015年05月07日 · 最后由 aidewoode 回复于 2015年05月08日 · 2071 次阅读

本人新手,才接触ember,现在有个问题被卡住了。所以请教一下论坛里的高手。

问题是这样的,我有一个post 页面,然后需要在post 页面里面加载相应的comments,

router是这样的

this.route("posts",{path: "/posts/:id"}, function() {
   this.route("comments");
 });

因为需要分页,所以写了posts.comments 的routes ,让其从后端加载分好的comments, 然后在posts 的template 里用{{outlet}} 加载comments的视图。

但现在就有个问题,我必须连接到 像xxxxx/posts/1/comments 这样的url 才能把post 和comments 都加载。 但是我想的是 能否从 xxxxx/posts/1 这样的url 就能加载完整的页面。好像貌似 {{render}} helper 可以,

然后我用render 加载试了一下,

{{render "posts.comments" posts.comments}} 

但是这样是错的, 因为 render 的第二个参数,要指定一个 model 类型,但是我想用的是posts.comments 的routes 里面的model, 貌似好像没法。

所以我想请教该如何解决这个问题呢??

共收到 4 条回复

你得区分一下 front 和 backend. 前端是不同的页面通过 route 在跳转, 而在 ember router 中准备数据. 你可以这样思考:

  1. PostRouter 中就加载好 posts 的第一页的 comments
  2. 写好 template 然后利用 {{render}} 传入 model
  3. 分页的操作在按照道理应该在 PostRouter 中的 actions 处理, 远程加载数据.

{{render}} helper 的特点在文档中有写:

{{render}} does several things:

* When no model is provided it gets the singleton instance of the corresponding controller
* When a model is provided it gets a unique instance of the corresponding controller
* Renders the named template using this controller
* Sets the model of the corresponding controller

当然你这个特点应该将 {{render}} 换为使用 {{partial}} , 只是部分 comments 的 html 片段不一样, 但是上下文中使用的 model 是一样的, 所以第二步中可以

  1. 在 template 中使用 {{partial 'comments'}} 不用传递当前 template 所对应的 controller 上下文中的 model, 他会自动拥有这个 context 可以直接使用
  2. 最好将 partial 使用的 template 使用 "_" 开头(类似 rails 中的 partial html 命名). 例如: _comments.hbs , 里面就直接 {{#each post.comments as |comment|}} 使用就好

{{partial}} 寻找的几个特点在文档中也有写:

* The partial helper renders another template without changing the template context
* If a "_nav" template isn't found, the partial helper will fall back to a template named "nav".  ({{partial "nav"}})
* The parameter supplied to partial can also be a path to a property containing a template name

#1楼 @wppurking

非常感谢啊, 非常好的方法啊,学习了,但是这样的话,会不会让posts的routes里面post 和comment 混在一起了,后端api 写出来感觉就不怎么清晰了,我想的是,能不能post 的routes里面用一个model,而在post.comments里面的routes里面用另外的一个model,加载post 相应的comments,然后再在post 的 的template 中加载对应comments的视图和model , 这样我感觉比较清晰, 不知道现在ember 能不能实现这样的要求啊?

@aidewoode 如果需要在 /posts/1 的页面里面查看 post 和分页的 comments 你的 URL 应该需要 /posts/1/comments?page=N 这种形式了

这样你的 Router 就是你上面写的那样, 而同时你需要手动准备

  • PostsCommentsRouter : 在这个里面准备你关于某个 post 的 comments 数据
  • PostsCommentsController : 在这里准备 template 里面的事件和需要收集的参数.
  • template/posts/comments.hbs : 这个与对应的 controller 对应使用.

这样设计 API 可能有点怪怪的, 例如: 你查看 topic 的 comments 理想的是 /topic/1 查看 topic 和这个 topic 的 comments, 要查看分页的 comments 会是 /topic/1?page=2 这样.

我说区分 front 和 backend 的意思是, 其实 Ember 提供 双向绑定 的好处就是, 你可以不用理睬 template 改如何展示你的 model 数据, 因为 Ember 让你的数据在前端是"活"的, 只要 Ember 所绑定的 data/model 发生变化 template 就会自动的变化, 而这个思维与 backend 中的数据变化则一定需要重新 get 一个页面不太一样.

另外, 我猜测你应该还是使用了 Ember-Data, 而 Ember-Data 中对于分页功能现在还没有尘埃落定(我们看起来简单, 实现起来还是有他们的难度) 参看两个 issue #1517 #2095 所以现在的意思就是, 如果我们要做分页, 还得自己想想办法, 当渲染了 posts 后, 在 PostsController 或者 PostsRouter 中自己再重新提交请求向 backend 要分页的 comments 数据, 再 push 到 store 中让 Ember 自动处理变化的数据. (你会发现 Discourse 的分页取巧了, 给了总个数, 但没有给页码, 而且是一直拖拽加载不是分页加载. 当然这种形式也挺适合他们的需求)

#3楼 @wppurking 确实是啊, 现在确实在用 ember-data ,前后端结合ember-cli-pagination 和will_paginate 进行分页,url 弄出来确实是很怪,看来如果没办法的话,还不得不自己实现一个分页了。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册