我想在Ember中创建一个类似于Netflix的界面,其中点击电影标题后,内容会在海报图片下面显示出来。我认为是用
创建一个嵌套路由Router.map(function() {
this.route('movies', {path: '/' }, function() {
this.route('movie', { path: '/:id'});
});
});
问题在于我不知道如何在每个电影组件中都有{{outlet}}
并告诉嵌套路由在相应的组件内呈现。有没有人创建类似于这种w /嵌套路线的东西?
答案 0 :(得分:3)
根据您是否不关心网址,想要查询参数,或者希望网址是完整路线,您可以采取不同的指示。
方法1:无网址状态
将movie-preview
和movie-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');
}
}
});