我想用Ember显示一条崩溃的路径。如何迭代当前路径?
在我看来,有两种方法:
余烬
编辑:请参阅下面的答案
我将这个问题与显示面包屑的当前状态保持同步。您可以浏览此问题的修订版以查看历史记录。
这里有几个目标:
控制器
App.ApplicationController = Ember.Controller.extend({
needs: ['breadcrumbs'],
currentPathDidChange: function() {
path = this.get('currentPath');
console.log('path changed to: ', path);
this.get('controllers.breadcrumbs').set('content',this.get('target.router.currentHandlerInfos'));
}.observes('currentPath')
});
App.BreadcrumbsController = Em.ArrayController.extend({});
路由器
App.ApplicationRoute = Ember.Route.extend({
renderTemplate: function() {
this.render();
this.render('breadcrumbs', {
outlet: 'breadcrumbs',
into: 'application',
controller: this.controllerFor('breadcrumbs')
});
}
});
模板
{{! application template }}
<div class="clearfix" id="content">
{{outlet "breadcrumbs"}}
{{outlet}}
</div>
{{! breadcrumbs template }}
<ul class="breadcrumb">
{{#each link in content}}
<li>
<a {{bindAttr href="link.name"}}>{{link.name}}</a> <span class="divider">/</span>
</li>
{{/each}}
</ul>
目前要解决的问题是:
#/websites/8/pages/1
时,面包屑的输出是:(我删除了所有脚本标记占位符<ul class="breadcrumb">
<li>
<a href="application" data-bindattr-34="34">application</a> <span class="divider">/</span></li>
<li>
<a href="sites" data-bindattr-35="35">sites</a> <span class="divider">/</span>
</li>
<li>
<a href="site" data-bindattr-36="36">site</a> <span class="divider">/</span>
</li>
<li>
<a href="pages" data-bindattr-37="37">pages</a> <span class="divider">/</span>
</li>
<li>
<a href="page" data-bindattr-38="38">page</a> <span class="divider">/</span>
</li>
<li>
<a href="page.index" data-bindattr-39="39">page.index</a> <span class="divider">/</span>
</li>
</ul>
{{#linkTo}}
硬编码到路线中,我尝试使其变得动态,例如here,但transitionTo
没有触发currentPath
-observer 另一种方式
大部分内容与上述相同,但存在一些差异。通过循环location.hash
而不是从路由器获取面包屑来制作面包屑。
ApplicationController 变为:
ApplicationController = Ember.Controller.extend({
needs: ['breadcrumbs'],
hashChangeOccured: function(context) {
var loc = context.split('/');
var path = [];
var prev;
loc.forEach(function(it) {
if (typeof prev === 'undefined') prev = it;
else prev += ('/'+it)
path.push(Em.Object.create({ href: prev, name: it }));
});
this.get('controllers.breadcrumbs').set('content',path)
}
});
ready : function() {
$(window).on('hashchange',function() {
Ember.Instrumentation.instrument("hash.changeOccured", location.hash);
});
$(window).trigger('hashchange');
}
我们需要在 ApplicationRoute
中订阅自定义处理程序App.ApplicationRoute = Ember.Route.extend({
setupController: function(controller, model) {
Ember.Instrumentation.subscribe("hash.changeOccured", {
before: function(name, timestamp, payload) {
controller.send('hashChangeOccured', payload);
},
after: function() {}
});
}
});
到目前为止,替代方法对我来说效果最好,但这并不是一种好方法,因为当您将路由器配置为使用history
代替location.hash
此方法时不再工作了。
答案 0 :(得分:3)
根据您当前的痕迹输出,我猜您路由器中有错误。
以下命令应返回包含当前痕迹的数组:
App.get('Router.router.currentHandlerInfos');
您的路由器应该嵌套:
this.resource('page 1', function () {
this.resource('page 2');
});
您可以在面包屑中使用#linkTo
代替a
标记,您将免费获得有效课程。
答案 1 :(得分:2)
我提出了一个更简单的解决方案,我发布到Ember discourse。
答案 2 :(得分:1)
我找到了一个( Ember-way )解决方案来显示面包屑。它基于路由器而不是我的location.hash
。
首先,我们需要在添加或删除breadcrumbs数组中的项目之前为面包屑设置基础结构。
在我的app.js中,我定义了一个NavItem
- 对象。这是所有可导航项目的框架。我用它来定义我的菜单项,但我们也将它用于面包屑。
App.NavItem = Em.Object.extend({
displayText: '',
routeName: ''
});
// define toplevel menu-items
App.dashboardMenuItem = App.NavItem.create({
displayText: 'Dashboard',
routePath: 'dashboard',
routeName: 'dashboard'
});
App.sitesMenuItem = App.NavItem.create({
displayText: 'Websites',
routePath: 'sites.index',
routeName: 'sites'
});
我们需要一个 BreadcrumbsController 来将面包屑放在一个中心位置
App.BreadcrumbsController = Em.ArrayController.extend({
content: []
});
我的 ApplicationController 取决于 BreadcrumbsController
App.ApplicationController = Ember.Controller.extend({
needs: ['breadcrumbs']
});
BreadcrumbsView 是 ApplicationView
的子视图App.ApplicationView = Ember.View.extend({
BreadcrumbsView: Ember.View.extend({
templateName: 'breadcrumbs',
init: function() {
this._super();
this.set('controller', this.get('parentView.controller.controllers.breadcrumbs'));
},
gotoRoute: function(e) {
this.get('controller').transitionToRoute(e.routePath);
},
BreadcrumbItemView: Em.View.extend({
templateName:'breadcrumb-item',
tagName: 'li'
})
})
});
在我的应用程序 -template中,我在插座上方输出了breadcrumbsview
{{view view.BreadcrumbsView}}
{{outlet}}
我正在使用Twitter Bootstrap,所以我的面包屑 -template的标记是
<ul class="breadcrumb">
{{#each item in controller.content}}
{{view view.BreadcrumbItemView itemBinding="item"}}
{{/each}}
</ul>
breadcrumb-item -template
<a href="#" {{action gotoRoute item on="click" target="view.parentView"}}>
{{item.displayText}}
</a> <span class="divider">/</span>
我们需要在应用中响应路由以更新面包屑。
当我的 SitesRoute (或任何其他顶层路线)被激活时,我们将NavItem推送到面包屑,但我也想用其余的顶层路线来做,所以我先创建 TopRoute
App.TopRoute = Em.Route.extend({
activate: function() {
this.controllerFor('menu').setActiveModule(this.get('routeName'));
var menuItem = app.menuItems.findProperty('routeName',this.get('routeName'));
this.controllerFor('breadcrumbs').get('content').pushObject(menuItem);
},
deactivate: function() {
var menuItem = app.menuItems.findProperty('routeName',this.get('routeName'));
this.controllerFor('breadcrumbs').get('content').removeObject(menuItem);
}
});
我的所有toproutes都是从这条路线延伸出来的,因此面包屑会自动更新
App.SitesRoute = App.TopRoute.extend();
对于更深层次,它的工作方式几乎相同,您只需使用activate
和deactivate
挂钩从Breadcrumbs中推送/删除对象
App.SiteRoute = Em.Route.extend({
activate: function() {
var site = this.modelFor('site');
this.controllerFor('breadcrumbs').get('content').pushObject(app.NavItem.create({
displayText: site.get('name'),
routePath: 'site',
routeName: this.get('routeName')
}));
},
deactivate: function() {
var site = this.modelFor('site');
this.controllerFor('breadcrumbs').get('content').removeAt(1);
}
});