2

我正在使用 twitter bootstrap 构建我的第一个 Web 应用程序,我很喜欢它,但我遇到了重复自己的问题。

我正在构建一个导航栏,我希望 UI 根据 url 反映哪个选项卡处于活动状态。我正在使用骨干网来路由网址。唯一的问题是我必须根据 url 手动将一堆不同的变量编码为“活动”或“”,以便选项卡反映适当的状态。

<template name="navbar">

<div class="container">
    <div class="row">
    <div class="span6">
    <ul class="nav nav-tabs">
        <li class="{{home}}">
            <a href="/home/">Home</a></li>

        <li class="{{1999s10}}{{1965malibu}}{{1960hearse}}{{1966gto}}{{1971blazer}} dropdown">
            <a class="dropdown-toggle" data-toggle="dropdown">Cars<b class="caret"></b></a>

            <ul class="dropdown-menu">
                <li class="{{1999s10}}"><a href="/cars/1999s10">1999 Electric S-10</a></li>
                <li class="{{1965malibu}}"><a href="/cars/1965malibu">1965 Malibu</a></li>
                <li class="{{1960hearse}}"><a href="/cars/1960hearse">1960 Hearse</a></li>
                <li class="{{1966gto}}"><a href="/cars/1966gto">1966 GTO</a></li>
                <li class="{{1971blazer}}"><a href="/cars/1971blazer">1971 Bazer</a></li>
                <!-- <li class="divider"></li> -->
            </ul>
        </li>  
    </div>
    </div>
</div>

如您所见,现在,我有一堆变量来指示哪些选项卡处于活动状态。我已经开始实现下面的代码,但是它太不优雅了,我已经停下来想使用更好的方法。

Template.navbar.home = function () {
    return Session.equals("active", "home") ? "active" : '';
};

// a bunch more of these for every route

var TodosRouter = Backbone.Router.extend({
    routes: {
        "home/": "home",
            // more routes
    },
    home: function () {
        Session.set("active", "home");
    },
    // more functions for capturing the routes and setting the session variable "active"
});

Router = new TodosRouter;

Meteor.startup(function () {
    Backbone.history.start({pushState: true});
});

使用这种方法:(1)有以数字开头的变量问题(我的错)(2)需要我路由每个 url 以相应地更改会话“活动”变量(3)需要我为每个导航栏中的按钮/网址

必须有更好的方法来做到这一点,但我还没有找到它。

重申一下,我想找到一种在不破坏 DRY(不要重复自己)编程原则的情况下完成激活必要选项卡的方法。

编辑:

真正好的是这样的:

<li class="{{(url=="/cars/1999s10/")?"active":""}}"><a href="/cars/1999s10">1999 Electric S-10</a></li>

那将是最少量的代码。

4

5 回答 5

6

您可以尝试创建一个全局 Handlebars 助手,该助手将路由名称作为参数并返回正确的类名:

if (Meteor.isClient) {
    Handlebars.registerHelper('TabClassName', function (route) {
        return Session.equals("active", route) ? "active" : "";
    });
}

然后在您的模板中,像这样调用助手:

<li class="{{TabClassName 'home'}}">
于 2012-10-28T00:45:45.333 回答
1

我发现了一些有用的东西:

Handlebars.registerHelper('TabActive', function (route) {
    var url = Session.get("url");
    var index = $.inArray(route, url);
    return (index != -1) ? "active" : "";
});


var TodosRouter = Backbone.Router.extend({
    routes: {
        "*url": "main"
    },
    main: function (url) {
        Session.set("url", url.split('/'))
    }
});

在 html 中," vs ' 至关重要!

<li class='{{TabActive "home"}}'>

这可行,但我唯一担心的是稍后将路由器用于其他网址......

于 2012-11-19T03:41:44.120 回答
0

我正在使用静态应用程序状态类来处理我的应用程序的当前状态。

它使用Session来存储当前状态。

在车把助手中,我测试了正确的状态

(咖啡稿)

Template.foo.helpers
  is_active: ->
    appState.isState appState.FOO

在模板中,我将使用它来设置我的链接样式

{{#if is_active}}
  <a href="/bar" class="active">/bar</a>
{{else}}
  <a href="/bar">/bar</a>
{{/if}}

appstate 对象非常简单

appState =
  FOO : "foo"
  BAR: "bar"

  setState: (state) ->
    Session.set(SESSION_STATE, state)

  getState: ->
    Session.get(SESSION_STATE)

  isState: (state) ->
    @getState() is state

如果在我的应用程序中的任何地方,appstate 发生了变化,那么反应魔法就会发生;)

appState.setState appState.LIST

更新:

使用rendered回调将活动类添加到导航项(未经测试!)

Template.foo.rendered = ->
  current = Backbone.history.fragment
  links = this.findAll("ul li a")

  links.forEach((link) ->
    $(link).parent().addClass("active") if link.href is current  
  )
于 2012-10-24T18:24:59.387 回答
0

正如 jtblin 指出的那样,您可以为此使用模板助手。下面的代码在 Meteor > 1.0 和 Iron Router > 0.9.4 下运行。

您可以传递正则表达式,而不是将路由名称传递给助手,如果您有子菜单,这将使其更合适。

# file: /client/helpers.coffee

Template.registerHelper 'activeMenuItem', (expression) ->
   reg = new RegExp(expression, 'i')
   if reg.test Router.current().route.getName() then "active" else ""

像这样在模板中使用帮助程序:

<li class="menu {{activeMenuItem 'persons'}}"> … </li>

这样,您将对所有以人员开头的路线(例如,personsList、personsAdd、personsEdit 等)重新“激活”。因此,如果您有子菜单,它也是一个很好的选择。

于 2014-11-27T15:16:08.923 回答
-1

我想出了以下非常通用的解决方案:

# Store currently selected bootstrap tab so that active state can be restored on reload

$(document).on 'click', 'a[data-toggle="tab"]', (e) ->
  Session.set("selected_tab", $(e.target).attr("href").replace("#", ""))

# Helper for determining active state of a tab navigation
Handlebars.registerHelper 'tab', ( options ) ->
  $el = $('<ul />').html( options.fn(this) )

  $selected_tab = $el.find('a[data-toggle="tab"][href=#' + Session.get("selected_tab") + ']')
  $selected_tab = $el.find('a[data-toggle="tab"]').first() if $selected_tab.length == 0

  # Mark navigation item as active
  $selected_tab.parent().addClass("active")

  # Mark content item as active
  $el.find($selected_tab.attr("href")).addClass("in active")

  return $el.html()

用法:

{{#tab}}
<ul class="nav nav-tabs">
  <li><a href="#article_tweet_pane" data-toggle="tab">Tweet</a></li>
  <li><a href="#article_blog_pane" data-toggle="tab">Blog</a></li>
  <li><a href="#article_newsletter_pane" data-toggle="tab">Newsletter</a></li>
</ul>

<div class="tab-content">
  <div id="article_tweet_pane" class="tab-pane fade">Tweet</div>
  <div id="article_blog_pane" class="tab-pane fade">Blog</div>
  <div id="article_newsletter_pane" class="tab-pane fade">Newsletter</div>
</div>
{{/tab}}
于 2013-07-22T12:20:15.870 回答