Ember.js:如何在嵌套路由场景中刷新父级路由模板?

12

我的页面布局(应用程序模板)看起来像这样(简化版):

Ember页面布局

我将其用于不同的路由(报价列表+报价详情,客户列表+客户详情)。列表显示在子导航出口。

我的路由器代码:

App.Router.map(function () {
    //...
    this.resource('offers', function () {
        this.resource('offer', { path: '/:offer_id' });
    });
}

我的路线:

App.OffersRoute = Ember.Route.extend({
   model: function () {
       return App.Offer.find();
   },
   renderTemplate: function (controller, model) {
       this.render('offer-list', { 
           into: 'application', outlet: 'sub-navigation', controller: 'offers' });
       this.render('offer-list-title', { into: 'application', outlet: 'page-title' });
       this.render('offer-list-content', { into: 'application' });
   }
});

App.OfferRoute = Ember.Route.extend({
   model: function (params) {
      return App.Offer.find(params.offer_id);
   },
   renderTemplate: function () {
      this.render('offer-title', { into: 'application', outlet: 'page-title' });
      this.render('offer-content', { into: 'application' });
   }
});

目前为止这个有效。

http://.../#/offers

显示列表和标题“Offer summary”以及静态html内容。我点击列表中的一个优惠,跳转到

http://.../#/offers/23

一切正常:它仍然在子导航区域中显示优惠列表以及正确的标题和优惠内容。

现在我的问题是:

如果我返回到

http://.../#/offers

如果使用菜单上的 #linkTo 辅助功能进入页面,那么 {{outlet}} / 内容区域会变为空(不像之前静态的 HTML),而且标题仍然是在 offer/23 路由中 {{page-title}} 的标题。

我该如何让我的应用程序 "重新渲染" 在 OffersRoute 中定义的模板,即 renderTemplate()

附注:我正在使用 Ember.js 1.0.0-RC.3 版本


你的菜单链接是如何构建的?如果直接访问链接引用的URL,您会得到相同的行为吗?我猜想当再次渲染路由时,该模型没有按预期构建。 - Lance Harper
@LanceHarper 1. 菜单中的链接是使用linkTo助手构建的:{{#linkTo“offers”}}所有优惠{{/linkTo}}--2. 直接在浏览器中插入URL访问页面对于所有页面都有效。 - splattne
1个回答

6
使用内置的Index路由并维护ApplicationRoute->OffersRoute->OfferRoute层次结构将解决您的问题。
如果您打开路由器转换日志,您会发现当导航到Offers时,实际上是进入了Offers.Index路由:
App = Ember.Application.create({
  LOG_TRANSITIONS: true
});

这意味着您可以在OffersIndexRoute中设置静态Offer标题和静态Offer内容,并且第一次正确设置后,如果您从内部的Offer详细信息页面链接回它,则再次设置。为使此功能正常工作,您还必须通过不直接将所有内容呈现到ApplicationRoute{{outlet}}来保留ApplicationRoute -> Offers -> Offer {{outlet}}层次结构。必须保留此层次结构的原因是,如果直接将子(Offer模板)呈现到Application模板中,则会删除Offers模板,当您尝试返回到OffersRoute时,其模板已被删除,因此什么都不会显示。

索引路由

使用OffersIndexRoute来填充ApplicationRoute{{outlet}}{{outlet page-title}}

JS:

//this renders the title and the main content for Offers
App.OffersIndexRoute = Ember.Route.extend({
  renderTemplate: function (controller, model) {
    this.render('offer-list-title', { into: 'application', outlet: 'page-title' });
    this.render();
  }
});

App.OffersRoute = Ember.Route.extend({
   model: function () {
       return App.Offer.find();
   },
   renderTemplate: function (controller, model) {
     this.render('offer-list', { 
         into: 'application', outlet: 'sub-navigation', controller: 'offers' });
     
     // render this in OffersIndexRoute instead
     //this.render('offer-list-title', { into: 'application', outlet: 'page-title' });
     
     this.render('offer-list-content', { into: 'application' });
   }
});

Handlebars:

<script type="text/x-handlebars" data-template-name="offer-list-content">
  {{outlet}}
</script>

<script type="text/x-handlebars" data-template-name="offers/index">
  Offers content
</script>  

offers-list-content中的插座将由OffersIndexRouteOffer模板填充,具体取决于当前路由是什么。

维护{{outlet}}层次结构

允许OfferRoute将其内容模板呈现到OffersRoute模板中,而不是强制呈现到ApplicationRoute中。

App.OfferRoute = Ember.Route.extend({
   model: function (params) {
      return App.Offer.find(params.offer_id);
   },
   renderTemplate: function () {
     this.render('offer-title', { into: 'application', outlet: 'page-title' });
     
     // preserve the hierarchy and render into the Offers {{outlet}}, which is the default
     //this.render('offer-content', { into: 'application' });
     this.render('offer-content');
   }
});

Working JSBin example


这个很好用,谢谢!实际上这应该是文档中的重点,甚至可以作为默认教程。也许将子视图渲染到主输出口应该是预期的行为,并将它们渲染到其父级输出口实现为一种特性...? - genkilabs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接