Pull to refresh

Nested routing в AngularJS

Reading time 2 min
Views 27K
image
В AngularJS, как известно, нет возможности штатными средствами сделать многоуровневую маршрутизацию, в которой перезагрузка нижних уровней маршрутов бы не приводила к пересозданию элементов верхнего уровня. Стандартный сервис $route инициализирует вид, контроллер и его scope целиком каждый раз, когда изменяется URL страницы.

Для решения этой проблемы написано несколько сторонних решений, включая известный ui-router. По ряду причин ни одно из решений для некоторых моих проектов не подошло, и я написал собственную библиотеку, которую здесь и представляю: angular-route-segment.

Что она позволяет делать?

Демонстрационный пример здесь: angular-route-segment.com/src/example
Исходники примера в каталоге example на Гитхабе.

Библиотека служит заменой стандартному сервису $route. Каждый маршрут представляется в виде иерархической древовидной цепочки сегментов, перечисленных через точку, каждый из которых возможно конфигурировать в отдельности.

angular.module('app').config(function ($routeSegmentProvider) {

$routeSegmentProvider.

    when('/section1',          's1.home').
    when('/section1/prefs',    's1.prefs').
    when('/section1/:id',      's1.itemInfo.overview').
    when('/section1/:id/edit', 's1.itemInfo.edit').
    when('/section2',          's2').

    segment('s1', {
        templateUrl: 'templates/section1.html',
        controller: MainCtrl}).

    within().

        segment('home', {
            templateUrl: 'templates/section1/home.html'}).

        segment('itemInfo', {
            templateUrl: 'templates/section1/item.html',
            controller: Section1ItemCtrl,
            dependencies: ['id']}).

        within().

            segment('overview', {
                templateUrl: 'templates/section1/item/overview.html'}).

            segment('edit', {
                 templateUrl: 'templates/section1/item/edit.html'}).

            up().

        segment('prefs', {
            templateUrl: 'templates/section1/prefs.html'}).

        up().

    segment('s2', {
        templateUrl: 'templates/section2.html',
        controller: MainCtrl});


Допускается использовать и иной синтаксис, без прохода по дереву:

$routeSegmentProvider.segment('s1', {
    templateUrl: 'templates/section1.html',
    controller: MainCtrl});

$routeSegmentProvider.within('s1').segment('home', {
    templateUrl: 'templates/section1/home.html'});

$routeSegmentProvider.within('s1').segment('itemInfo', {
    templateUrl: 'templates/section1/item.html',
    controller: Section1ItemCtrl,
    dependencies: ['id']});


С помощью директивы app-view-segment (замена штатному ng-view) указывается место в DOM страницы, куда каждый из уровней сегментов должен быть отрендерен:

index.html
<ul>
    <li><a href="/section1">Section 1</a></li>
    <li><a href="/section2">Section 2</a></li>
</ul>
<div id="contents" app-view-segment="0"></div>


section1.html (будет загружен в элемент div#contents)
<h4>Section 1</h4>
Section 1 contents.
<div app-view-segment="1"></div>


В этот может быть загружен следующий сегмент, и так далее.

Такой подход, в сочетании с некоторыми продвинутыми фичами по конфигурированию, позволяет делать довольно сложные вещи с маршрутизацией в приложении.
Tags:
Hubs:
+25
Comments 19
Comments Comments 19

Articles