Ember JS中嵌套路由的动态插座

时间:2016-06-24 23:36:26

标签: ember.js ember-cli

我想在Ember中创建一个类似于Netflix的界面,其中点击电影标题后,内容会在海报图片下面显示出来。我认为是用

创建一个嵌套路由
Router.map(function() {
  this.route('movies', {path: '/' }, function() {
    this.route('movie', { path: '/:id'});
  });
});

问题在于我不知道如何在每个电影组件中都有{{outlet}}并告诉嵌套路由在相应的组件内呈现。有没有人创建类似于这种w /嵌套路线的东西?

enter image description here

1 个答案:

答案 0 :(得分:3)

根据您是否不关心网址,想要查询参数,或者希望网址是完整路线,您可以采取不同的指示。

方法1:无网址状态

movie-previewmovie-detail转换为组件。

您可以在此使用focus。这样,选择不同的电影预览将取消对焦一个组件并聚焦另一个组件,而无需更新任何绑定。

在movie-preview.js

export default Component.extend({
  attributeBindings: ['tabindex'],
  tabindex: 0,
  isFocused: false,
  movie: undefined,

  focusIn() {
    this.set('isFocused', true);
  },

  focusOut() {
      this.set('isFocused', false);
  }
});

在电影预览的模板中,我们添加一个条件。

{{#if isFocused}}
  {{movie-detail movie=movie}}
{{/if}}

但是,我们是否希望将此状态反映到URL中?让我们从如何为查询参数执行此操作开始。

方法2:查询参数

在路线的控制器上,为selected添加query param

在此路由的模板中,我们将使用eq(一个帮助程序,其中一个可能的实现是here)来设置isFocused,具体取决于该预览的电影是否为目前选定的一个。我们还传递了一个设置焦点的动作。

{{#each movies as | movie |}}   {{电影预览     电影=电影     isFocused =(eq movie.id选中)     select =(action“selectMovie”movie.id)   }} {{/每}}

movie-preview.js将被更改以触发点击选择。

export default Component.extend({
  isFocused: false,
  movie: undefined,
  select: undefined,

  click() {
    this.sendAction('select');
  }
});

最后,我们需要在控制器中为此路线处理此操作。

export default Controller.extend({
  queryParams: ['selected'],
  selected: undefined,

  actions: {
    selectMovie(movieId) {
      this.set('selected', movieId);
    }
  }
});

但也许我们想要这个有一个漂亮的网址?这也很容易。

方法3:漂亮网址

第一步是设置嵌套路由,如图所示。

this.route('movies', {path: '/' }, function() {
  this.route('movie-detail', { path: '/:id'});
});

为此,我们确实需要您最初建议的outlet,但我们不需要对方法2中的代码进行那么多更改。而不是movie-detail组件,我们现在有一个电影细节路线。既然我们之前不需要知道这个细节,我现在也会跳过它。我们只关心“激活”路线的机制。

在电影预览的模板中,我们更改条件以包装插座。

{{#if isFocused}}
  {{outlet}}
{{/if}}

在控制器中,我们需要触发转换,而不是修改查询参数。

export default Controller.extend({
  selected: undefined,

  actions: {
    selectMovie(movieId) {
      this.set('selected', movieId);

      this.transitionToRoute('movies.movie-detail', movieId);
    },

    clearSelection() {
      this.set('selected', undefined);
      this.transitionToRoute('movies');
    }
  }
});