首页 > ember关于模板嵌套模板的问题。

ember关于模板嵌套模板的问题。

模板文件类似如下,有个sidebar的左侧导航栏,右侧是主工作区域

 <div class="container-fluid">
<div class="row">
    <div class="col-sm-3 col-md-2 sidebar">
        {{outlet sidebar}}
    </div>
    <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
         {{outlet}}
    </div>
</div>

目前我的解决方案是在路由中加入指定controller来渲染左侧的导航栏

App.IndexRoute = Ember.Route.extend({
model: function () {
    return this.store.find('applicationInfo', 1); //获取应用系统信息
},
renderTemplate: function () {
    this.render(); // Render default outlet   
    this.render('sidebar', { // the template to render
        into: 'index', // the template to render into
        controller: 'sidebar', // the controller to use for the template
        outlet: 'sidebar' // the name of the outlet in that template
    });
}});

以下是controller代码

App.SidebarController = Ember.ArrayController.extend({
model:[{
        id: 1,
        moduleName: '系统设置',
        subModules: [{
            id: 11,
            moduleName: '栏目管理'
    }]
}, {
        id: 2,
        moduleName: '用户角色'
}, {
        id: 3,
        moduleName: '权限管理'
}]});

似乎左侧的sidebar没办法指定具体路由的方式只能指定控制器来获取数据,如果我的数据要从服务器端读取,请问我该怎么处理sidebarcontroller?或者是否有更好的处理类似这种导航这块的模块,毕竟每个页面都有。希望能有更好的最佳实践方式


首先,路由是有继承关系的,如果你有一些数据是要全局共享的(比如说你的 sidebar 是全局的),那么它的数据就应该从最顶层的路由获取到(于是底下无论哪一层子路由都无需重复去请求这些数据),最顶层的路由也就是 ApplicationRoute

其次,你这个例子其实可以简化成:

<div class="container-fluid">
  <div class="row">
    <div class="col-sm-3 col-md-2 sidebar">
      {{partial 'sidebar'}}
    </div>
    <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
      {{outlet}}
    </div>
  </div>
</div>

变化在第四行,是的,没有必要用 outlet。一般来说 outlet 是一个资源的子路由的入口,这句话是什么意思呢?

比如说我有一个:this.resource('posts'),那么这里的 posts 就是一个资源,它有一个 PostIndexRoute 是此类资源共享的路由入口(默认就有),在 PostIndexRoute 对应的模板内声明 outlet,那么属于 posts 资源下的其他子路由就从这里进入,比如 neweditshow/:post_id 等等。

其实 Application 本身就是一个资源,而且是整个应用最顶层的资源,所以它也会有一个 IndexRoute。在你的例子里,你的困惑来自于你不知道 sidebar 对应的路由是什么。然而你没有考虑到的问题是,对于 Application 这个资源来说,sidebar 算是一个子路由吗?它需要一个 outlet 吗?

答案是:看情况。的确有更复杂的应用场景值得把 sidebar 当成一个子路由,但显然不是你这个例子。

在你的例子里,sidebar 作为 Application 的一个 partial 就够了,它不需要独立的路由和控制器,它的数据就直接从 ApplicationRoute 里获取即可。

然后右半部分是首页缺省显示的则和之前一样来自 IndexRoute 就可以了,你都用不着 renderTemplate


然后说说复杂的情况。假设出于某种原因我就是希望 sidebar 有独立的控制器,不要和 ApplicationController 搀和在一起呢?那么你可以用 {{render 'sidebar'}}render 会提供一个独立的控制器(与模板同名,也就是 SidebarController),它的数据来自于当前作用域,也可以自己指定一个 model 给它(自己查文档)。

那么到底能不能像你的例子里一样用 {{outlet}} 呢?技术上说,可以;但是不应该这么做。

因为进入 outlet 的内容应当是有独立的路由的,有独立的路由就意味着至少有一种 URL 的形态是可以对应到它的。想想看,你的 sidebar 是全局都有的,你可能需要一种 www.xxx.com/sidebar 这样的 URL 来对应它吗?显然不!所以你试图为 sidebar 找一个单属于它的路由本身就是没道理的。

但是我们的确可以在技术上创造一个不去对应独立 URL 的 outlet,可以利用 setupController 来手动指明路由提供给其他控制器的 model。比如像这样:

App.IndexRoute = Ember.Route.extend({
  model: function () {
    return this.store.find('applicationInfo', 1); //获取应用系统信息
  },
  renderTemplate: function () {
    this.render();
    this.render('sidebar', {
      into: 'index',
      controller: 'sidebar',
      outlet: 'sidebar'
    });
  },
  setupController: function (controller, model) {
    controller.set('model', model);
    this.controllerFor('sidebar').set('model', this.store.find('sidebarInfo'));
  }
});

像这样,SidebarController 的数据其实还是来自于 IndexRoute,只不过是你显式指明的而已。重要的是,没有独立的路由,也就不会出现 www.xxx.com/sidebar 这种毫无必要的 URL 了。

【热门文章】
【热门文章】