Ember.js предлагает мощный механизм для работы с маршрутизацией, который помогает управлять навигацией в приложении. Одной из важнейших концепций в этом механизме является использование вложенных маршрутов (Nested Routes). Вложенные маршруты позволяют строить сложную иерархию URL, что полезно для организации крупных веб-приложений. Этот подход даёт возможность более эффективно управлять состоянием и представлением на различных уровнях иерархии, а также уменьшить повторяемость кода.
Маршруты в Ember.js связывают URL-адреса с соответствующими
контроллерами и шаблонами. Когда пользователь переходит по URL,
соответствующий маршрут и его обработчик активируются, и приложение
рендерит соответствующее представление. В базовой форме маршруты в
Ember.js представляют собой объекты, которые наследуют функциональность
от Ember.Route.
Основная структура маршрута:
Router.map(function() {
this.route('home');
this.route('about');
});
Каждый маршрут соответствует конкретному URL и связан с определённым шаблоном. Но что делать, если приложение должно отображать несколько частей интерфейса на разных уровнях URL? Для этого и используются вложенные маршруты.
Вложенные маршруты позволяют строить иерархию маршрутов. Каждый маршрут может иметь дочерние маршруты, которые активируются при переходе на определённый подурл. Это позволяет создавать комплексные структуры навигации, где каждый уровень может быть ответственен за свой набор данных и представлений.
Пример:
Router.map(function() {
this.route('home', function() {
this.route('profile');
this.route('settings');
});
});
Здесь маршрут home имеет два вложенных маршрута —
profile и settings. Структура URL будет
следующей:
/home — отображает общий шаблон для маршрута
home./home/profile — отображает шаблон для маршрута
home.profile./home/settings — отображает шаблон для маршрута
home.settings.Вложенные маршруты также требуют вложенной структуры шаблонов. Каждый
родительский маршрут может содержать в себе блок
{{outlet}}, который будет служить точкой для рендеринга
шаблонов дочерних маршрутов.
Пример:
{{!-- app/templates/home.hbs --}}
<h1>Home Page</h1>
{{outlet}}
{{!-- app/templates/home/profile.hbs --}}
<h2>Profile Page</h2>
{{!-- app/templates/home/settings.hbs --}}
<h2>Settings Page</h2>
В шаблоне home.hbs используется {{outlet}},
чтобы отобразить контент дочерних маршрутов, таких как
profile.hbs и settings.hbs.
Когда используется вложенная маршрутизация, каждый маршрут может
запрашивать свои собственные данные. Для этого можно использовать метод
model в маршруте, который позволяет загружать данные для
каждого уровня иерархии.
Пример:
// app/routes/home.js
import Route from '@ember/routing/route';
export default class HomeRoute extends Route {
model() {
return {
message: 'Welcome to the Home page'
};
}
}
// app/routes/home/profile.js
import Route from '@ember/routing/route';
export default class ProfileRoute extends Route {
model() {
return {
username: 'JohnDoe'
};
}
}
Когда пользователь переходит на /home/profile, Ember.js
загружает модель для маршрута home.profile, который может
использовать свои собственные данные, не вмешиваясь в логику
родительского маршрута.
Контроллеры в Ember.js управляют состоянием данных и обеспечивают их связывание с шаблонами. Каждый вложенный маршрут может иметь свой собственный контроллер, что даёт возможность управлять состоянием на разных уровнях приложения.
Пример:
// app/controllers/home.js
import Controller from '@ember/controller';
export default class HomeController extends Controller {
title = 'Home Page';
}
// app/controllers/home/profile.js
import Controller from '@ember/controller';
export default class ProfileController extends Controller {
username = 'JohnDoe';
}
Контроллеры могут быть использованы для управления состоянием в
разных частях интерфейса. Родительский контроллер может передавать
данные в дочерний через модель или использовать
controller-связи для обеспечения координации между
уровнями.
queryParams — это параметры, которые могут быть
добавлены к URL и которые позволяют изменять состояние маршрута, не
изменяя сам путь. В вложенных маршрутах можно работать с
query-параметрами, чтобы менять состояние на различных уровнях.
Пример:
// app/routes/home/profile.js
import Route from '@ember/routing/route';
export default class ProfileRoute extends Route {
queryParams = {
showDetails: {
refreshModel: true
}
};
model(params) {
return {
showDetails: params.showDetails
};
}
}
При переходе на маршрут /home/profile?showDetails=true
параметр showDetails будет доступен в модели маршрута и
контроллере. Это позволяет делать интерфейс динамичным, без
необходимости перезагружать всю страницу.
Вложенные маршруты также могут содержать динамические сегменты. Это позволяет создавать более гибкие маршруты, где часть URL зависит от переменных значений.
Пример:
Router.map(function() {
this.route('user', { path: '/user/:user_id' }, function() {
this.route('profile');
});
});
Здесь маршрут user имеет динамический сегмент
user_id, который может быть использован для отображения
информации о конкретном пользователе. При переходе на
/user/123/profile, можно получить идентификатор
пользователя и загрузить его профиль.
Для того чтобы рендерить вложенные шаблоны в родительский маршрут,
используется компонент {{outlet}}. Важно помнить, что
{{outlet}} — это точка, в которой будут отображаться
шаблоны дочерних маршрутов. Каждый вложенный маршрут имеет свой
собственный outlet, который обеспечивает разделение
контента на разных уровнях.
{{!-- app/templates/user.hbs --}}
<h1>User Profile</h1>
{{outlet}}
{{!-- app/templates/user/profile.hbs --}}
<h2>Profile Page for {{model.user_id}}</h2>
Таким образом, вложенная структура маршрутов и шаблонов в Ember.js позволяет эффективно управлять сложными приложениями, делая их более организованными и легкими для сопровождения.
Вложенные маршруты в Ember.js обеспечивают гибкость в построении
сложных иерархий URL. Важно правильно настроить модель, контроллеры и
шаблоны для разных уровней маршрутов, чтобы обеспечить эффективную
работу и взаимодействие между ними. Использование
queryParams и динамических сегментов делает маршруты ещё
более мощными, позволяя создавать динамичные веб-приложения с
минимальными усилиями.