Выделение текущего состояния навигации в приложении Backbone.js - PullRequest
8 голосов
/ 22 августа 2011

Я хочу выделить текущее состояние навигации.Например, если hashchange равен #home, я хочу по-другому оформить ссылку меню «Домой» и аналогично другим ссылкам.

Backbone.js запускает отдельные события, такие как route:home, ... route:some-other, когда#home и другие ссылки нажимаются.Я не мог видеть ни одного обычного события, которое будет запускаться для каждого хэша.После этого мне необходимо написать логику выделения состояния, привязав все события маршрута, что, на мой взгляд, не является хорошим решением.

Итак, я переопределил Backbone.Router.route в моем подклассе / объекте маршрутизатора,как

// override backbone' Router.route method to publish 
// common 'route_change' event for any hash change
route : function(route, name, callback) {
    Backbone.history || (Backbone.history = new Backbone.History);
    if (!_.isRegExp(route)) route = this._routeToRegExp(route);
    Backbone.history.route(route, _.bind(function(fragment) {
        var args = this._extractParameters(route, fragment);
        callback.apply(this, args);
        this.trigger.apply(this, ['route:' + name].concat(args));

        // ADDED BY: ManiKanta G
        // name: route method
        // fragment: route path
        // args: any additional args
        this.trigger.apply(this, ['route_change'].concat(name, fragment, args));
    }, this));
}

Это будет публиковать общее событие route_change для каждого хешигена и передачи name, fragment и других args, используя которые я выделяю состояние в одном месте..

Мой вопрос заключается в том, нужно ли мне переопределять метод Backbone, как этот, или есть какой-нибудь механизм сборки, который я могу использовать здесь.Если нет, я хотел бы видеть подобное поведение в Backbone.js

Редактировать: пример программы

Router = Backbone.Router.extend({
    routes : {
        '': 'root', 
        'home': 'home',
        'about':'about'
    },

    // app routing methods
    root: function () { console.log('root route');  },
    home: function () { console.log('home route');  },
    about: function () { console.log('about route'); }

});

Router.bind('all', function () {
    console.log('all route...');
});

router = new Router();

и навигацию с использованиемвышеупомянутый маршрутизатор:

router.navigate('home', true);

выход: home route

Обновление о том, почему вышеуказанная программа не работает:

мы должны связать событие all с Router instance, но не с самим Router, поэтому изменение Router.bind('all', ... на router.bind('all', ...) заставит вышеуказанную программу работать

Ответы [ 4 ]

7 голосов
/ 10 сентября 2011

В магистрали 0.5.x вы можете привязать событие all к экземпляру маршрутизатора, и первым аргументом передачи вашему обработчику будет маршрут

Вот пример на jsfiddle , воспроизведенный здесь:

var dummy = Backbone.Router.extend({
    defaultPage: 'messages',

    routes: {
        '': 'index',
        'index': 'index',
        'mailbox': 'mailbox'
    },

    index: function() {
        // code here
    },

    mailbox: function() {
        // code here
    }
});

var router = new dummy();

router.bind('all', function(route) {
    document.write('triggered: ' + route + '<br/>');
});

router.navigate('index', true);
router.navigate('mailbox', true);
2 голосов
/ 19 сентября 2011

Вот пример из одного из моих приложений:

routes.bind('all ', function(route, section) {
    var $el;
    route = route.replace('route: ', '');

    $el = $('#nav - ' + route);

    // If current route is highlighted, we're done.
    if ($el.hasClass('selected')) {
        return;
    } else {
        // Unhighlight active tab.
        $('#menu li.selected').removeClass('selected');
        // Highlight active page tab.
        $el.addClass('selected');
    }
});
0 голосов
/ 23 марта 2015

Вот что я делаю:

@router.bind 'all', (route) ->
  # this triggers twice for every route; ignore the second time
  return if route == "route"

  # ex: route="route:home", name="home", href="#home"
  name = route.replace('route:', '')

  # remove the active class on all of the current nav links
  $("#menu li.active").removeClass('active')

  # add it back to the link that has an href that ends in `name`
  $("#menu a[href$='#{name}']").parent().addClass('active')
0 голосов
/ 08 апреля 2012

Я столкнулся с проблемой, заключающейся в том, что при первой загрузке страницы меню не было выделено, поскольку событие произошло до того, как была инициирована привязка. я исправил это, используя историю:

$('#menu li.'+Backbone.history.fragment).addClass('active');
...