Clean Ember 1.13+ 了解子路由是否激活的方法
Clean Ember 1.13+ way of knowing if child route is activated
假设我们有一个 Article
模型如下:
export default DS.Model.extend({
author: DS.belongsTo('user'),
tagline: DS.attr('string'),
body: DS.attr('string'),
});
还假设我们有很多页面,并且在每个页面上我们都想要一个显示全新文章标语的行情收录器。由于它在每个页面上,我们在 应用程序根 级别加载所有(新)文章,并让组件显示它们:
{{taglines-ticker articles=articles}}
{{output}}
这样我们就可以访问任何嵌套页面并查看标语(无需将组件添加到每个页面)。
问题是,我们不想在查看文章时看到文章的代码标语,但根级别taglines-ticker
不知道激活了什么子路由,所以我们不能简单地按 params.article_id
进行过滤。有没有一种干净的方法可以将该信息传递给父路由?
注:
这 不是 how to determine active child route in Ember 2? 的副本,因为它不涉及显示 {{link-to}}
的活动链接
您仍然可以使用 link-to
组件来完成此操作,我认为这是一种简单的方法。您没有共享 taglines-ticker
模板,但在其中您必须为每篇文章提供某种列表。创建一个从 link-to
组件扩展而来的新 tagline-ticker
组件,然后使用它的 activeClass
和 current-when
属性在当前路由时隐藏标语。它不需要是 link,或者根本不需要看起来像 link。
tagline-ticker.js
:
export default Ember.LinkComponent.extend({
// div or whatever you want
tagName: 'div',
classNames: ['whatever-you-want'],
// use CSS to make whatever class you put here 'display: none;'
activeClass: 'hide-ticker',
// calculate the particular route that should hide this tag in the template
'current-when': Ember.computed(function() {
return `articles/${this.get('article.id')}`;
}),
init() {
this._super(arguments);
// LinkComponents need a params array with at least one element
this.attrs.params = ['articles.article'];
},
});
tagline-ticker
用于 taglines-ticker.hbs
:
{{#tagline-ticker}}
Article name
{{/tagline-ticker}}
CSS:
.hide-ticker {
display: none;
}
Ember 正在 2.15 中添加适当的 router
服务;这会公开有关当前路由的信息以及一些允许检查路由器状态的方法。在旧版本的 Ember 上有一个 polyfill,它可能适合你,具体取决于你当前使用的版本:
根据引入该服务的 RFC,有一个 isActive
method 可用于检查特定路由当前是否处于活动状态。在不知道 tagline-ticker
的代码的情况下,很难确切地知道它是如何使用的。但是,我会想象您正在迭代传入的 articles
,因此您可以执行以下操作:
export default Ember.Component.extends({
router: Ember.inject.service(),
articles: undefined,
filteredArticles: computed('articles', 'router.currentRoute', function() {
const router = this.get('router');
return this.get('articles').filter(article => {
// Return `false` if this particular article is active (YMMV based on your code)
return !router.isActive('routeForArticle', article);
});
})
});
然后,您可以在您的模板中遍历 filteredArticles
,您将只有当前未显示的模板。
我试图扩展 LinkComponent
,但我 运行 遇到了几个问题,但仍然无法让它与 current-when
一起工作。此外,如果多个组件需要基于子路由执行相同的逻辑,它们 all 需要从 LinkComponent
扩展并执行相同的样板文件才能使其正常工作。
因此,根据@kumkanillam 的评论,我使用服务实现了这一点。它工作得非常好,除了必须访问组件中某处的服务才能观察它。
(参见 很棒 question/answer。)
services/current-article.js
export default Ember.Service.extend({
setId(articleId) {
this.set('id', articleId);
},
clearId() {
this.set('id', null);
},
});
routes/article.js
export default Ember.Route.extend({
// Prefer caching currently viewed article ID via service
// rather than localStorage
currentArticle: Ember.inject.service('current-article'),
activate() {
this._super(arguments);
this.get('currentArticle').setId(
this.paramsFor('articles.article').article_id);
},
deactivate() {
this._super(arguments);
this.get('currentArticle').clearId();
},
... model stuff
});
components/taglines-ticker.js
export default Ember.Component.extend({
currentArticle: Ember.inject.service('current-article'),
didReceiveAttrs() {
// The most annoying thing about this approach is that it
// requires accessing the service to be able to observe it
this.get('currentArticle');
},
filteredArticles: computed('currentArticle.id', function() {
const current = this.get('currentArticle.id');
return this.get('articles').filter(a => a.get('id') !== current);
}),
});
更新:
如果改为从 controller/parent 组件传递服务,则可以消除 didReceiveAttrs
挂钩。
controllers/application.js
export default Ember.Controller.extend({
currentArticle: Ember.inject.service('current-article'),
});
templates/application.hbs
{{taglines-ticker currentArticle=currentArticle}}
... model stuff
});
components/taglines-ticker.js
export default Ember.Component.extend({
filteredArticles: computed('currentArticle.id', function() {
const current = this.get('currentArticle.id');
return this.get('articles').filter(a => a.get('id') !== current);
}),
});
假设我们有一个 Article
模型如下:
export default DS.Model.extend({
author: DS.belongsTo('user'),
tagline: DS.attr('string'),
body: DS.attr('string'),
});
还假设我们有很多页面,并且在每个页面上我们都想要一个显示全新文章标语的行情收录器。由于它在每个页面上,我们在 应用程序根 级别加载所有(新)文章,并让组件显示它们:
{{taglines-ticker articles=articles}}
{{output}}
这样我们就可以访问任何嵌套页面并查看标语(无需将组件添加到每个页面)。
问题是,我们不想在查看文章时看到文章的代码标语,但根级别taglines-ticker
不知道激活了什么子路由,所以我们不能简单地按 params.article_id
进行过滤。有没有一种干净的方法可以将该信息传递给父路由?
注:
这 不是 how to determine active child route in Ember 2? 的副本,因为它不涉及显示 {{link-to}}
您仍然可以使用 link-to
组件来完成此操作,我认为这是一种简单的方法。您没有共享 taglines-ticker
模板,但在其中您必须为每篇文章提供某种列表。创建一个从 link-to
组件扩展而来的新 tagline-ticker
组件,然后使用它的 activeClass
和 current-when
属性在当前路由时隐藏标语。它不需要是 link,或者根本不需要看起来像 link。
tagline-ticker.js
:
export default Ember.LinkComponent.extend({
// div or whatever you want
tagName: 'div',
classNames: ['whatever-you-want'],
// use CSS to make whatever class you put here 'display: none;'
activeClass: 'hide-ticker',
// calculate the particular route that should hide this tag in the template
'current-when': Ember.computed(function() {
return `articles/${this.get('article.id')}`;
}),
init() {
this._super(arguments);
// LinkComponents need a params array with at least one element
this.attrs.params = ['articles.article'];
},
});
tagline-ticker
用于 taglines-ticker.hbs
:
{{#tagline-ticker}}
Article name
{{/tagline-ticker}}
CSS:
.hide-ticker {
display: none;
}
Ember 正在 2.15 中添加适当的 router
服务;这会公开有关当前路由的信息以及一些允许检查路由器状态的方法。在旧版本的 Ember 上有一个 polyfill,它可能适合你,具体取决于你当前使用的版本:
根据引入该服务的 RFC,有一个 isActive
method 可用于检查特定路由当前是否处于活动状态。在不知道 tagline-ticker
的代码的情况下,很难确切地知道它是如何使用的。但是,我会想象您正在迭代传入的 articles
,因此您可以执行以下操作:
export default Ember.Component.extends({
router: Ember.inject.service(),
articles: undefined,
filteredArticles: computed('articles', 'router.currentRoute', function() {
const router = this.get('router');
return this.get('articles').filter(article => {
// Return `false` if this particular article is active (YMMV based on your code)
return !router.isActive('routeForArticle', article);
});
})
});
然后,您可以在您的模板中遍历 filteredArticles
,您将只有当前未显示的模板。
我试图扩展 LinkComponent
,但我 运行 遇到了几个问题,但仍然无法让它与 current-when
一起工作。此外,如果多个组件需要基于子路由执行相同的逻辑,它们 all 需要从 LinkComponent
扩展并执行相同的样板文件才能使其正常工作。
因此,根据@kumkanillam 的评论,我使用服务实现了这一点。它工作得非常好,除了必须访问组件中某处的服务才能观察它。
(参见
services/current-article.js
export default Ember.Service.extend({
setId(articleId) {
this.set('id', articleId);
},
clearId() {
this.set('id', null);
},
});
routes/article.js
export default Ember.Route.extend({
// Prefer caching currently viewed article ID via service
// rather than localStorage
currentArticle: Ember.inject.service('current-article'),
activate() {
this._super(arguments);
this.get('currentArticle').setId(
this.paramsFor('articles.article').article_id);
},
deactivate() {
this._super(arguments);
this.get('currentArticle').clearId();
},
... model stuff
});
components/taglines-ticker.js
export default Ember.Component.extend({
currentArticle: Ember.inject.service('current-article'),
didReceiveAttrs() {
// The most annoying thing about this approach is that it
// requires accessing the service to be able to observe it
this.get('currentArticle');
},
filteredArticles: computed('currentArticle.id', function() {
const current = this.get('currentArticle.id');
return this.get('articles').filter(a => a.get('id') !== current);
}),
});
更新:
如果改为从 controller/parent 组件传递服务,则可以消除 didReceiveAttrs
挂钩。
controllers/application.js
export default Ember.Controller.extend({
currentArticle: Ember.inject.service('current-article'),
});
templates/application.hbs
{{taglines-ticker currentArticle=currentArticle}}
... model stuff
});
components/taglines-ticker.js
export default Ember.Component.extend({
filteredArticles: computed('currentArticle.id', function() {
const current = this.get('currentArticle.id');
return this.get('articles').filter(a => a.get('id') !== current);
}),
});