Статьи

Одностраничные приложения с ngRoute и ngAnimate в AngularJS

Одностраничные приложения позволяют обновлять определенную часть веб-страницы путем маршрутизации любого содержимого, хранящегося в отдельном файле .html. При этом вы не перезагружаете свою главную страницу.

AngularJS предоставляет модуль с именем ngRoute именно для этой цели.

Еще один полезный модуль AngularJS — это ngAnimate, который позволяет легко анимировать с помощью определенных классов CSS.

В этом уроке я постараюсь подробно объяснить каждый шаг, хотя вам все еще нужны базовые знания AngularJS, чтобы иметь возможность следовать им.

Этот файл index.html станет нашей главной страницей, где у нас есть как фиксированный, так и маршрутизированный контент.

Я начну с базового HTML-документа и style.css все необходимые библиотеки вместе с нашей пользовательской style.css стилей с именем style.css и файлом JavaScript angularApp.js .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
<html>
<head>
    <link href=»style.css» rel=»stylesheet»>
</head>
<body>
 
<script src=»https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js»></script>
<script src=»//ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular-route.js»></script>
<script src=»//ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular-animate.js»></script>
 
<script src=»angularApp.js»></script>
 
</body>
</html>

Теперь я добавляю два DIV с именами идентификаторов fixedContent и routedContent внутри mainWrapper DIV.

routedContent также routedContent в другой DIV- routedContent именем wrapper . Это связано с тем, что значение routedContent должно быть абсолютным относительно родительского DIV из-за того факта, что во время анимации маршрутизации два разных фрагмента контента конфликтуют друг с другом.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
<html>
<head>
    <link href=»style.css» rel=»stylesheet»>
</head>
<body>
<div id=»mainWrapper»>
    <div id=»fixedContent»></div>
    <div id=»wrapper»>
        <div id=»routedContent» ng-view></div>
    </div>
</div>
 
<script src=»https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js»></script>
<script src=»//ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular-route.js»></script>
<script src=»//ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular-animate.js»></script>
 
<script src=»angularApp.js»></script>
 
</body>
</html>

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

Чтобы определить приложение Angular в нашем HTML-файле, нам нужно использовать директиву ng-app . Поскольку вся страница будет приложением Angular, нам нужно назначить эту директиву mainWrapper DIV.

Нам также нужна директива ng-view , которая сообщает DIV, что она назначена для отображения содержимого перенаправленной страницы.

Теперь наш файл index.html выглядит так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
<html>
<head>
    <link href=»style.css» rel=»stylesheet»>
</head>
<body>
<div id=»mainWrapper» ng-app=»mainApp»>
    <div id=»fixedContent»></div>
    <div id=»wrapper»>
        <div id=»routedContent» ng-view></div>
    </div>
</div>
 
<script src=»https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js»></script>
<script src=»//ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular-route.js»></script>
<script src=»//ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular-animate.js»></script>
 
<script src=»angularApp.js»></script>
 
</body>
</html>

Нам нужно навигационное меню, чтобы направлять различные фрагменты контента в ng-view .

Мы собираемся использовать ul и элементы для создания простого горизонтального меню. Ниже вы можете увидеть фрагмент HTML для структуры меню.

1
2
3
4
5
6
7
8
<div id=»fixedContent»>
    <ul>
        <a href=»#page1″>Page1</a>
        <a href=»#page2″>Page2</a>
        <a href=»#page3″>Page3</a>
        <a href=»#page4″>Page4</a>
    </ul>
</div>

По умолчанию модуль ng-route использует ! приставка. Однако здесь мы используем только # перед нашими страницами для маршрутизации. Это делается с hashPrefix атрибута hashPrefix используемого в конфигурации, который я объясню позже в соответствующем разделе. А пока прими это как есть.

Наш окончательный HTML-файл выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<html>
<head>
    <link href=»style.css» rel=»stylesheet»>
</head>
<body>
<div id=»mainWrapper» ng-app=»mainApp»>
    <div id=»fixedContent»>
        <ul>
            <a href=»#page1″>Page1</a>
            <a href=»#page2″>Page2</a>
            <a href=»#page3″>Page3</a>
            <a href=»#page4″>Page4</a>
        </ul>
    </div>
    <div id=»wrapper»>
        <div id=»routedContent» ng-view></div>
    </div>
</div>
 
<script src=»https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js»></script>
<script src=»//ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular-route.js»></script>
<script src=»//ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular-animate.js»></script>
 
<script src=»angularApp.js»></script>
 
</body>
</html>

Поскольку этот урок посвящен AngularJS, я не буду подробно останавливаться на стилях CSS. Если у вас есть знания CSS, стилизуйте страницу по своему желанию. В противном случае вы можете использовать стиль, который я приведу ниже.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
html, body{
    margin: 0;
    padding: 0;
}
 
#mainWrapper{
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-top: 50px
}
 
#fixedContent{
    margin-bottom: 50px;
}
 
#wrapper{
    width: 350px;
}
 
#routedContent{
    width: 350px;
    position: absolute;
}
 
ul{
    display: flex;
    justify-content: space-between;
    width: 350px;
    margin: 0;
    padding: 0;
}
 
a{
    text-decoration: none;
    color: #FFFFFF;
    font-family: Arial;
 
    list-style: none;
    background-color: #cecece;
    padding: 7px 10px;
    border-radius: 2px;
}

Каждая страница, которая будет перенаправлена ​​в DIV с директивой ng-view внутри основного файла HTML, может иметь уникальную структуру HTML и стиль CSS.

Давайте начнем с page1.html .

Так как мы хотим определенный стиль для каждой страницы, нам нужны отдельные файлы CSS для каждой страницы. Поэтому мы также создаем файл с именем page1.css , который будет содержать правила стилизации page1.html .

Основная структура HTML для page1 выглядит следующим образом:

1
2
3
4
5
6
<link href=»page1.css» rel=»stylesheet»>
 
<div id=»page1″>
    <h1>Page 1</h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>

Вверху мы связались с CSS-файлом, который будет стилизовать страницу, и объявили DIV с идентификатором page1 , в который будет page1 весь контент.

Я сделаю это простым, но вам решать, как структурировать HTML-файл. Просто помните, что вашим контейнером всегда будет DIV, которому назначена директива ng-view . Таким образом, все в ваших перенаправленных страницах будет относительно этого DIV.

Стили page1.html приведены ниже:

1
2
3
4
5
6
7
#page1{
    font-family: Arial;
}
 
h1{
    color: #ffa42a;
}

Остальные три страницы могут быть совершенно разными, но для простоты я просто использую один и тот же шаблон для каждой HTML-страницы и немного разные CSS-файлы (разные цвета текста h1 ).

1
2
3
4
5
6
<link href=»page2.css» rel=»stylesheet»>
 
<div id=»page2″>
    <h1>Page 2</h1>
    <p>Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur?
</div>
1
2
3
4
5
6
7
#page2{
    font-family: Arial;
}
 
h1{
    color: cornflowerblue;
}
1
2
3
4
5
6
<link href=»page3.css» rel=»stylesheet»>
 
<div id=»page3″>
    <h1>Page 3</h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
1
2
3
4
5
6
7
#page3{
    font-family: Arial;
}
 
h1{
    color: #b2ce6f;
}
1
2
3
4
5
6
<link href=»page4.css» rel=»stylesheet»>
 
<div id=»page4″>
    <h1>Page 4</h1>
    <p>Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur?
</div>

1
2
3
4
5
6
7
#page4{
    font-family: Arial;
}
 
h1{
    color: #ff4517;
}

На данный момент мы завершили все необходимые файлы HTML и CSS. Теперь пришло время написать код JavaScript, который управляет маршрутизацией и анимацией.

Поскольку наша директива ng-app называется mainApp , мы используем этот идентификатор в функции модуля. Нам также нужно включить зависимости ngRoute и ngAnimate .

mainAngular = angular.module('mainApp',['ngRoute', 'ngAnimate']);

Теперь у нас есть доступ к $routeProvider и $locationProvider .

Мы будем использовать $routeProvider для управления маршрутизацией и $locationProvider для изменения hashPrefix , для которого установлено значение ! по умолчанию.

Мы используем .when('/page1', {templateUrl: 'page1.html'}) чтобы определить страницу, которая будет перенаправлена ​​при нажатии <a href="#page1">Page1</a> в нашем основном HTML-файле.

Мы повторяем одну и ту же строку кода для каждой перенаправляемой страницы. В конце мы используем .otherwise({redirectTo: '/page1'}) , который обрабатывает неожиданные имена страниц. Если вы попытаетесь посетить неопределенное имя страницы, скажем page5 , вы будете перенаправлены на page1 .

Полный код JavaScript ниже:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var mainAngular = angular.module(‘mainApp’,[‘ngRoute’, ‘ngAnimate’]);
 
mainAngular.config(function ($routeProvider, $locationProvider) {
    $routeProvider
        .when(‘/page1’,{
            templateUrl: ‘page1.html’
        })
        .when(‘/page2’,{
            templateUrl: ‘page2.html’
        })
        .when(‘/page3’,{
            templateUrl: ‘page3.html’
        })
        .when(‘/page4’,{
            templateUrl: ‘page4.html’
        })
        .otherwise({
            redirectTo: ‘/page1’
        });
 
    $locationProvider.hashPrefix(»);
 
});

Дополнительное примечание:   Если вы хотите добавить конкретную директиву ng-controller для любых страниц, подлежащих маршрутизации, вы можете обработать это внутри $routeProvider .

Пример для page1 :

1
2
3
4
.when(‘/page1’,{
    templateUrl: ‘page1.html’,
    controller: ‘page1Controller’
})

В конце наша страница должна выглядеть следующим образом, и вы сможете перемещаться между страницами без анимации перехода.

Конечный результат после стайлинга и маршрутизации

Теперь пришло время оживить переходы маршрута.

Для анимации AngularJS имеет встроенные CSS-классы благодаря зависимости ngAnimate.

Те классы, которые мы собираемся использовать:

  • ng-enter : начальные стили CSS для анимации ввода.
  • ng-enter-active : завершающие стили CSS для анимации ввода.
  • ng-leave : начальные стили CSS для анимации выхода.
  • ng-leave-active : завершающие стили CSS для анимации отпуска.

Таким образом, перенаправленный контент, поступающий на главную страницу, имеет переход от ng-enter к ng-enter-active . Аналогично, содержимое, покидающее главную страницу, имеет переход от ng-leave к ng-leave-active .

Мы должны присоединить вышеупомянутые классы к нашему классу routedContent .

Пример перехода приведен ниже. Вы можете создать свою собственную анимацию перехода или использовать ее в своем файле style.css .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#routedContent.ng-enter{
    transform: translateX(-500px);
    opacity: 0;
 
    -webkit-transition: all 0.35s cubic-bezier(1,.01,0,.99);
    -moz-transition: all 0.35s cubic-bezier(1,.01,0,.99);
    -ms-transition: all 0.35s cubic-bezier(1,.01,0,.99);
    -o-transition: all 0.35s cubic-bezier(1,.01,0,.99);
    transition: all 0.35s cubic-bezier(1,.01,0,.99);
}
 
#routedContent.ng-enter-active{
    transform: translateX(0px);
    opacity: 1;
}
 
#routedContent.ng-leave{
    transform: translateX(0);
    opacity: 1;
 
    -webkit-transition: all 0.35s cubic-bezier(1,.01,0,.99);
    -moz-transition: all 0.35s cubic-bezier(1,.01,0,.99);
    -ms-transition: all 0.35s cubic-bezier(1,.01,0,.99);
    -o-transition: all 0.35s cubic-bezier(1,.01,0,.99);
    transition: all 0.35s cubic-bezier(1,.01,0,.99);
}
 
#routedContent.ng-leave-active{
    transform: translateX(500px);
    opacity: 0;
}

Я создал репозиторий GitHub с конечным результатом . Вы можете скачать или клонировать код там, чтобы попробовать его.

В этом уроке мы рассмотрели, как создавать приложения SPA с помощью модуля ng-route AngularJS, а затем анимировали переходы с помощью CSS-классов ng-animate .

Используя только четыре CSS-класса, предоставляемых ng-animate , вы можете создавать различные анимации. Вы всегда можете прикрепить дополнительные классы, чтобы иметь больше контроля над анимацией перехода. Например, вы можете сделать так, чтобы ваши переходы страниц учитывали направление.

Я также упомянул, что, прикрепляя директиву controller к каждой конкретной странице внутри $routeProvider , вы можете получить дополнительный контроль над каждой страницей.

JavaScript с его библиотеками, такими как Angular, стал одним из де-факто языков работы в сети. Это не без кривых обучения, и есть множество фреймворков и библиотек, которые также могут вас занять. Если вы ищете дополнительные ресурсы для обучения или использования в своей работе, посмотрите, что у нас есть на Envato Market .

Я надеюсь, что этот урок дал вам общее представление о том, как использовать модули ng-route и ng-animate вместе.