Обзор
Прежде всего, давайте посмотрим, что я имею в виду под «Динамическими ярлыками». Представьте себе проект, в котором есть множество пользователей, и каждому из них нужен ярлык или горячая клавиша для открытия информационного модального окна. Конечно, не совсем уместно заставлять всех пользователей использовать только определенный ярлык для этого действия. Даже у некоторых пользователей может быть глобальный ярлык, точно такой же, как у вас, который имеет совершенно другую функциональность в другом программном обеспечении.
И вот тут-то и появляются «Динамические ярлыки»! Использование динамических сочетаний клавиш позволяет использовать разные горячие клавиши для любых действий в зависимости от того, что удобно пользователям. Поэтому нам необходимо получить всю пользовательскую конфигурацию пользователя при входе в систему.
Чтобы добиться динамических ярлыков в angular, нам нужно реализовать две основные части:
- Структура данных
- Ключевой слушатель
Служба и структура данных
Начните с создания службы для хранения всей логики и обработчиков с помощью angular cli:
Предполагая, что вы следуете руководству по стилю angular для структуры вашего проекта.
ng generate service core/services/shortcut
Затем, чтобы имитировать конфигурации ярлыков пользователя, мы создаем интерфейс для представления структуры данных ярлыков. Наш интерфейс может быть примерно таким:
export interface Shortcut {
/**
* Our shortcut is defined here as a string
*/
key: string;
/**
* An identifier about what this shortcut is going to do
*/
action: string;
}
И мы помещаем этот интерфейс в файл с именем shortcut.service.d.ts
рядом с нашей службой ярлыков. Теперь у нас есть ярлыки для примера в поле класса ShortcutService
:
configuration: Shortcut[] = [
{
key: 'Ctrl+B',
action: 'GoToHome'
},
{
key: 'Ctrl+M',
action: 'Logout',
}
];
Итак, как вы видите, здесь я хочу перейти на домашнюю страницу, когда нажимаю Ctrl+B
. И я хочу выйти, используя Ctrl+M
.
Реализовать прослушиватель ключей
Теперь, когда у нас есть ярлыки, мы должны быть в состоянии прослушивать событие клавиатуры keydown
на цели window
. Для этого лучше всего создать наблюдаемое из события с помощью rxjs и сохранить его в поле в нашем сервисе:
В соответствии с соглашением об именовании наблюдаемых объектов мы назовем его
keydown$
.
keydown$ = fromEvent(window, 'keydown');
Нам также нужно поле для хранения подписки, чтобы мы могли отписаться от нее и избежать утечки памяти:
keydownSubscription: Subscription;
Затем мы добавляем метод для подписки на этот пользовательский наблюдаемый объект, чтобы мы могли вызывать его из других компонентов, чтобы начать прослушивание:
start(): void {
this.keydownSubscription = this.keydown$.subscribe((event: KeyboardEvent) => {
for (const shortcut of this.configuration) {
let shouldBeCtrl = false;
let shouldBeAlt = false;
let targetKey = '';
// Parse shortcut text to know what should be keys
const keys = shortcut.key.toLocaleLowerCase().split('+');
for (const key of keys) {
switch (key) {
case 'ctrl': shouldBeCtrl = true; break;
case 'alt': shouldBeAlt = true; break;
default: targetKey = key;
}
}
if (
event.ctrlKey === shouldBeCtrl
&& event.altKey === shouldBeAlt
&& targetKey === event.key
) {
this.actionHandler(shortcut.action);
break;
}
}
});
}
Как вы видите, в этом методе мы анализируем каждое сочетание клавиш, чтобы увидеть, каким должно быть событие, соответствующее нашему ярлыку. Затем, если все является тем, чем оно «должно быть», мы можем вызвать обработчик действий и разорвать цикл. Обработчик действия может быть таким:
actionHandler(action: string): void {
switch (action) {
case 'GoToHome': /* Ex: Navigate to home */ break;
case 'Logout': /* Ex: Clear the local storage */ break;
default: /* Warning about invalid action */
}
}
И, наконец, последний метод — это не что иное, как метод stop
для отмены подписки на этот пользовательский наблюдаемый объект и отмены прослушивания событий клавиатуры:
stop(): void {
if (this.keydownSubscription) {
this.keydownSubscription.unsubscribe();
}
}
Теперь угадайте, что?
У вас могут быть разные ярлыки для разных страниц в вашем приложении, и это совершенно нормально! Просто добавьте этот метод:
changeShortcuts(shortcuts: Shortcut[]) {
this.configuration = shortcuts;
}
И теперь вы можете изменить набор ярлыков и действий, когда захотите :)