角度服务回调命令组合



Setup

我一直在研究一个用于创建动态键盘快捷键的 API,该快捷键适用于任何给定的 Angular 组件。以下是用于表示Shortcut的模型:

export class Shortcut {
keyCode: number;
command: Function;
args?: any;
constructor(keyCode: number, command: Function, args?: any[]) {
this.keyCode = keyCode;
this.command = command;
if (args) {
this.args = args;
}
}
}

预期用途如下:

// function called in component OnInit function
initializeShortcuts() {
this.shortcutService
.addShortcut(
KeyCodes.One, 
this.md.createMarkdown, 
[this.mdEditor, '#']
);      
}

在组件模板中,根据文本区域检查keydown事件,文本区域又调用ShortcutService上的checkShortcut函数。以下是整个服务:

import { Injectable } from '@angular/core';
import { Shortcut } from './shortcut';

@Injectable()
export class ShortcutService {
shortcuts = new Array<Shortcut>();
checkShortcut(event: KeyboardEvent) {
if (event.ctrlKey) {
const result = this.shortcuts.filter((s: Shortcut) => {
return s.keyCode === event.keyCode;
})[0];
if (result) {
console.log(result);
event.preventDefault();
result.args ? result.command(...result.args) : result.command();
}
}
}
addShortcut(keyCode: number, command: Function, args?: any[]) {
this.shortcuts.push(new Shortcut(keyCode, command, args));
}
removeShortcut(shortcut: Shortcut) {
const index = this.shortcuts.indexOf(shortcut);
this.shortcuts.splice(index, 1);
}
}

问题

正如我现在所拥有的,它可以工作,但我必须在回调函数本身中显式定义任何支持函数,因为this上下文不可用,如MarkdownService所示:

createMarkdown(editor: ElementRef, markdown: string) {
function getEditorValues(editor: ElementRef): EditorValues {
return new EditorValues(
editor.nativeElement.selectionStart,
editor.nativeElement.selectionEnd,
editor.nativeElement.value.length,
editor.nativeElement.value
);
}
const values = getEditorValues(editor);
if (values.start === values.end) {
editor.nativeElement.value = `${values.zeroToStart}${markdown}${values.startToLength}`;
} else {
editor.nativeElement.value =  `${values.zeroToStart}${markdown}${values.startToLength}`;
}
}  

如果我在服务本身中定义getEditorValues()并在分配values常量时引用该函数调用,则会引发错误,因为对象未定义。

有没有更好的方法来实现这样的事情,其中依赖功能可以在回调函数之外访问?

例如,参见StackBlitz项目。

您可以通过用箭头函数包装函数来保留函数的this上下文。而不是传递这个:

this.md.createMarkdown

通过以下内容:

(...params) => this.md.createMarkdown(...params)

或者,您可以通过传递以下内容来绑定this

this.md.createMarkdown.bind(this)

最新更新