Backbone.js предоставляет минималистичную структуру для создания клиентских приложений, упрощая организацию кода через модели, коллекции, представления и маршрутизаторы. Одной из важных задач интерактивного интерфейса является управление клавиатурой. В современных веб-приложениях навигация с помощью клавиш может значительно улучшить пользовательский опыт.
В Backbone.js события клавиатуры обычно обрабатываются внутри
View через привязку слушателей DOM-событий. Backbone
позволяет использовать объект events для удобного
связывания событий с методами класса:
var KeyboardView = Backbone.View.extend({
el: '#app',
events: {
'keydown': 'handleKeyDown',
'keyup': 'handleKeyUp'
},
initialize: function() {
this.$el.attr('tabindex', 0); // Делает элемент фокусируемым
this.$el.focus();
},
handleKeyDown: function(event) {
switch(event.key) {
case 'ArrowUp':
this.moveUp();
break;
case 'ArrowDown':
this.moveDown();
break;
case 'Enter':
this.selectItem();
break;
}
},
handleKeyUp: function(event) {
// Логика при отпускании клавиши, если нужна
},
moveUp: function() {
console.log('Движение вверх');
},
moveDown: function() {
console.log('Движение вниз');
},
selectItem: function() {
console.log('Элемент выбран');
}
});
Ключевые моменты:
tabindex необходим для того, чтобы элемент мог
получать фокус и принимать события клавиатуры.keydown и keyup позволяют
обрабатывать нажатия клавиш с разной семантикой: keydown —
для мгновенной реакции, keyup — для завершения
действия.switch или if для
определения нажатой клавиши по event.key обеспечивает
гибкость в управлении навигацией.Для организации клавиатурной навигации между элементами интерфейса часто используется коллекция моделей и визуальных представлений (Views). Например, список элементов можно обернуть в Backbone Collection и управлять активным элементом через индекс:
var Item = Backbone.Model.extend({});
var ItemCollection = Backbone.Collection.extend({
model: Item
});
var ItemListView = Backbone.View.extend({
initialize: function(options) {
this.collection = options.collection;
this.activeIndex = 0;
this.render();
},
events: {
'keydown': 'onKeyDown'
},
render: function() {
this.$el.empty();
this.collection.each(function(item, index) {
var itemView = $('<div>').text(item.get('name'));
if(index === this.activeIndex) itemView.addClass('active');
this.$el.append(itemView);
}, this);
},
onKeyDown: function(event) {
if(event.key === 'ArrowDown') {
this.activeIndex = Math.min(this.collection.length - 1, this.activeIndex + 1);
this.render();
}
if(event.key === 'ArrowUp') {
this.activeIndex = Math.max(0, this.activeIndex - 1);
this.render();
}
}
});
Особенности реализации:
render, что обеспечивает синхронизацию модели и
интерфейса.activeIndex служит для отслеживания текущего выбранного
элемента.Math.min и Math.max
предотвращает выход индекса за пределы коллекции.Иногда необходимо реагировать на клавиши независимо от того, какой
элемент в фокусе. Для этого можно привязывать обработчики к
document или window:
var GlobalKeyboard = Backbone.View.extend({
initialize: function() {
$(document).on('keydown', this.handleGlobalKeyDown.bind(this));
},
handleGlobalKeyDown: function(event) {
if(event.key === 'Escape') {
console.log('Закрыть модальное окно');
}
},
remove: function() {
$(document).off('keydown', this.handleGlobalKeyDown.bind(this));
}
});
Важно:
remove)..bind(this) позволяет сохранить контекст
view внутри обработчика.ArrowUp,
ArrowDown, Enter, Escape,
Tab) делает интерфейс предсказуемым.Эта схема позволяет строить сложные и интерактивные интерфейсы с полноценной поддержкой клавиатурной навигации, сохраняя структуру и преимущества Backbone.js.