用余烬显示崩溃路径

时间:2013-02-28 09:23:07

标签: ember.js breadcrumbs ember-router

我想用Ember显示一条崩溃的路径。如何迭代当前路径?

在我看来,有两种方法:

余烬

编辑:请参阅下面的答案

我将这个问题与显示面包屑的当前状态保持同步。您可以浏览此问题的修订版以查看历史记录。

这里有几个目标:

  1. 听取路线改变
  2. 查找当前路线
  3. 显示当前路线的列表
  4. 显示路线中步骤的工作链接
  5. 控制器

    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>
    

    目前要解决的问题是:

    • 当我转到URL:#/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此方法时不再工作了。

3 个答案:

答案 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();

对于更深层次,它的工作方式几乎相同,您只需使用activatedeactivate挂钩从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);   
    }
});