22

我在我的 Ember.js 应用程序中使用 Twitter Bootstrap 进行导航。Bootstrap 使用标签active上的类来包装导航链接,而不是在链接本身上设置类。liactive

Ember.js 的新linkTo助手将active在链接上设置一个类,但(据我所知)不提供任何挂钩该属性的功能。

现在,我正在使用这种丑陋的方法:

{{#linkTo "inbox" tagName="li"}}
  <a {{bindAttr href="view.href"}}>Inbox</a>
{{/linkTo}}

这将输出:

<li class="active" href="/inbox"><a href="/inbox">Inbox</a></li>

这是我想要的,但不是有效的 HTML。

我还尝试从父视图绑定到生成的 LinkView 的active属性,但如果这样做,父视图将在插入之前渲染两次,这会触发错误。

除了手动重新创建linkTo助手内部使用的逻辑以将active类分配给链接之外,是否有更好的方法来实现此效果?

4

9 回答 9

27

我们肯定需要一个更公开、更永久的解决方案,但这样的事情现在应该可行。

模板:

<ul>
{{#view App.NavView}}
  {{#linkTo "about"}}About{{/linkTo}}
{{/view}}

{{#view App.NavView}}
  {{#linkTo "contacts"}}Contacts{{/linkTo}}
{{/view}}
</ul>

视图定义:

App.NavView = Ember.View.extend({
  tagName: 'li',
  classNameBindings: ['active'],

  active: function() {
    return this.get('childViews.firstObject.active');
  }.property()
});

这依赖于几个约束:

  • 导航视图包含单个静态子视图
  • 您可以为您<li>的 s 使用视图。文档中有很多关于如何从 JavaScript 定义或 Handlebars 自定义视图元素的详细信息。

我已经提供了这个工作的现场 JSBin

于 2013-01-14T23:49:32.843 回答
9

好吧,我采用了 @alexspeller 的好主意并将其转换为 ember-cli:

应用程序/组件/链接-li.js

export default Em.Component.extend({
    tagName: 'li',
    classNameBindings: ['active'],
    active: function() {
        return this.get('childViews').anyBy('active');
    }.property('childViews.@each.active')
});

在我的导航栏中,我有:

{{#link-li}}
    {{#link-to "squares.index"}}Squares{{/link-to}}
{{/link-li}}
{{#link-li}}
    {{#link-to "games.index"}}Games{{/link-to}}
{{/link-li}}
{{#link-li}}
    {{#link-to "about"}}About{{/link-to}}
{{/link-li}}
于 2014-07-26T16:22:32.060 回答
8

您还可以使用嵌套链接:

{{#link-to "ccprPracticeSession.info" controller.controllers.ccprPatient.content content tagName='li' href=false eventName='dummy'}}
  {{#link-to "ccprPracticeSession.info" controller.controllers.ccprPatient.content content}}Info{{/link-to}}
{{/link-to}}
于 2013-09-02T13:50:31.533 回答
6

基于 katz 的回答,您可以在单击activenav 元素时重新计算该属性parentView

App.NavView = Em.View.extend({

    tagName: 'li',
    classNameBindings: 'active'.w(),

    didInsertElement: function () {
        this._super();
        var _this = this;
        this.get('parentView').on('click', function () {
            _this.notifyPropertyChange('active');
        });
    },

    active: function () {
        return this.get('childViews.firstObject.active');
    }.property()
});
于 2013-01-30T20:10:31.707 回答
5

我刚刚编写了一个组件来使它更好一点:

App.LinkLiComponent = Em.Component.extend({
  tagName: 'li',
  classNameBindings: ['active'],
  active: function() {
    return this.get('childViews').anyBy('active');
  }.property('childViews.@each.active')
});

Em.Handlebars.helper('link-li', App.LinkLiComponent);

用法:

{{#link-li}}
  {{#link-to "someRoute"}}Click Me{{/link-to}}
{{/link-li}}
于 2014-04-24T00:43:09.803 回答
2

我重新创建了内部使用的逻辑。其他方法似乎更骇人听闻。这也将使在我可能不需要路由的其他地方重用逻辑变得更加容易。

像这样使用。

{{#view App.LinkView route="app.route" content="item"}}{{item.name}}{{/view}}

App.LinkView = Ember.View.extend({
    tagName: 'li',
    classNameBindings: ['active'],
    active: Ember.computed(function() {
      var router = this.get('router'),
      route = this.get('route'),
      model = this.get('content');
      params = [route];

      if(model){
        params.push(model);
      }

      return router.isActive.apply(router, params);
    }).property('router.url'),
    router: Ember.computed(function() {
      return this.get('controller').container.lookup('router:main');
    }),
    click: function(){
        var router = this.get('router'),
        route = this.get('route'),
        model = this.get('content');
        params = [route];

        if(model){
            params.push(model);
        }

        router.transitionTo.apply(router,params);
    }
});
于 2013-01-24T19:34:49.373 回答
1

您可以跳过扩展视图并使用以下内容。

{{#linkTo "index" tagName="li"}}<a>Homes</a>{{/linkTo}}

即使没有 href,Ember.JS 仍然知道如何连接到 LI 元素。

于 2014-02-26T16:08:03.517 回答
0

对于同样的问题,我使用了基于 jQuery 的解决方案,不确定性能损失,但它是开箱即用的。我重新打开 Ember.LinkView 并扩展它。

Ember.LinkView.reopen({
    didInsertElement: function(){
        var el = this.$();

        if(el.hasClass('active')){
            el.parent().addClass('active');
        }

        el.click(function(e){
            el.parent().addClass('active').siblings().removeClass('active');
        });
    }
});
于 2013-09-01T05:18:29.540 回答
0

撰写本文时的当前答案已过时。在更高版本的 Ember 中,如果您使用它,当当前路由与目标链接匹配时,{{link-to}}它会自动'active'在元素上设置类。<a>

因此,只需编写您的 css 并期望<a>将具有active并且它应该开箱即用地做到这一点。

幸运的是,添加了该功能。之前解决这个“问题”所需的所有东西都是非常荒谬的。

于 2014-07-09T22:49:17.047 回答