Backbone.js предоставляет мощный механизм маршрутизации через объект
Router, позволяющий управлять состоянием приложения в
зависимости от URL. В сложных приложениях возникает необходимость
организации вложенных маршрутов, когда один маршрут
может иметь несколько подмаршрутов, каждый из которых управляет
отдельным представлением или логикой.
Маршрутизатор Backbone создается с помощью расширения
Backbone.Router:
var AppRouter = Backbone.Router.extend({
routes: {
"": "home",
"posts": "showPosts",
"posts/:id": "showPost"
},
home: function() {
console.log("Главная страница");
},
showPosts: function() {
console.log("Список постов");
},
showPost: function(id) {
console.log("Просмотр поста с id:", id);
}
});
Каждый маршрут связывает URL-шаблон с методом, который выполняет необходимую логику.
Вложенные маршруты позволяют разделить функциональность приложения на иерархические уровни. Например, можно иметь общий маршрут для раздела «Посты» и подмаршруты для отдельных действий: просмотр, редактирование, создание.
Пример структуры вложенных маршрутов:
#posts
├─ /posts → список постов
├─ /posts/:id → просмотр поста
└─ /posts/:id/edit → редактирование поста
var PostsRouter = Backbone.Router.extend({
routes: {
"": "list",
":id": "view",
":id/edit": "edit"
},
list: function() {
console.log("Список всех постов");
},
view: function(id) {
console.log("Просмотр поста:", id);
},
edit: function(id) {
console.log("Редактирование поста:", id);
}
});
var AppRouter = Backbone.Router.extend({
routes: {
"posts*actions": "handlePosts"
},
handlePosts: function(actions) {
if (!this.postsRouter) {
this.postsRouter = new PostsRouter();
Backbone.history.loadUrl("posts" + actions);
}
}
});
В данном примере:
posts.PostsRouter.Backbone.history.loadUrl позволяет запустить
маршрутизацию внутри вложенного маршрутизатора.Вложенные маршрутизаторы часто нуждаются в доступе к общему состоянию приложения. Для этого используют:
Backbone.Model и
Backbone.Collection)Backbone.Events) для синхронизации
действийПример событийной шины:
var vent = _.extend({}, Backbone.Events);
var PostsRouter = Backbone.Router.extend({
routes: {
"": "list",
":id": "view"
},
list: function() {
vent.trigger("posts:list");
},
view: function(id) {
vent.trigger("posts:view", id);
}
});
vent.on("posts:list", function() {
console.log("Отображение списка постов через шину событий");
});
vent.on("posts:view", function(id) {
console.log("Отображение поста через шину событий, id:", id);
});
Такой подход позволяет:
При вложенной маршрутизации важно корректно обрабатывать перенаправления и возврат к предыдущему состоянию. Для этого Backbone предоставляет метод:
Backbone.history.navigate(fragment, {trigger: true});
fragment — путь для навигацииtrigger: true — немедленный вызов соответствующего
маршрутаПример использования при переходе между подмаршрутами:
vent.on("posts:view", function(id) {
Backbone.history.navigate("posts/" + id, {trigger: true});
});
Вложенные маршруты часто требуют динамического построения
URL. Backbone позволяет использовать шаблоны с параметрами
(:id, *actions).
Пример сложного подмаршрута:
"posts/:postId/comments/:commentId/edit": "editComment"
Метод маршрутизатора получит оба параметра:
editComment: function(postId, commentId) {
console.log("Редактирование комментария", commentId, "в посте", postId);
}
Каждый маршрут должен создавать или обновлять соответствующее представление:
var PostView = Backbone.View.extend({
render: function(post) {
this.$el.html("<h2>" + post.get("title") + "</h2>");
return this;
}
});
var postView = new PostView({el: "#content"});
vent.on("posts:view", function(id) {
var post = postsCollection.get(id);
postView.render(post);
});
Такой подход позволяет разделять маршрутизацию и визуализацию, делая код гибким и поддерживаемым.
Вложенная маршрутизация в Backbone.js обеспечивает мощный механизм управления сложными приложениями, позволяя структурировать код по разделам, управлять состоянием и обеспечивать модульность без потери гибкости.