文档键盘模块

键盘模块

Keyboard 模块支持在特定上下文中自定义键盘事件的行为。Quill 使用它来绑定格式化热键,并防止浏览器出现不良副作用。

¥The Keyboard module enables custom behavior for keyboard events in particular contexts. Quill uses this to bind formatting hotkeys and prevent undesirable browser side effects.

按键绑定

¥Key Bindings

键盘处理程序绑定到特定的按键和按键修饰符。key 是 JavaScript 事件按键代码,但允许使用字母数字键和一些常用按键的字符串简写。

¥Keyboard handlers are bound to a particular key and key modifiers. The key is the JavaScript event key code, but string shorthands are allowed for alphanumeric keys and some common keys.

快捷键包括:metaKeyctrlKeyshiftKeyaltKey。此外,shortKey 是一个特定于平台的修饰符,相当于 Mac 上的 metaKey 以及 Linux 和 Windows 上的 ctrlKey

¥Key modifiers include: metaKey, ctrlKey, shiftKey and altKey. In addition, shortKey is a platform specific modifier equivalent to metaKey on a Mac and ctrlKey on Linux and Windows.

处理程序将在 this 绑定到键盘实例的情况下调用,并传递当前选择范围。

¥Handlers will be called with this bound to the keyboard instance and be passed the current selection range.

quill.keyboard.addBinding({
key: 'b',
shortKey: true
}, function(range, context) {
this.quill.formatText(range, 'bold', true);
});
// addBinding may also be called with one parameter,
// in the same form as in initialization
quill.keyboard.addBinding({
key: 'b',
shortKey: true,
handler: function(range, context) {
}
});

如果修饰键为 false,则假定修饰键处于非活动状态。你也可以传递 null 来表示修饰符的任意值。

¥If a modifier key is false, it is assumed to mean that modifier is not active. You may also pass null to mean any value for the modifier.

// Only b with no modifier will trigger
quill.keyboard.addBinding({ key: 'b' }, handler);
// Only shift+b will trigger
quill.keyboard.addBinding({ key: ['b', 'B'], shiftKey: true }, handler);
// Either b or shift+b will trigger
quill.keyboard.addBinding({ key: ['b', 'B'], shiftKey: null }, handler);

多个处理程序可以绑定到同一个按键和修饰符组合。处理程序将按照绑定的顺序同步调用。默认情况下,一个处理程序会停止传递到下一个处理程序,除非它显式返回 true

¥Multiple handlers may be bound to the same key and modifier combination. Handlers will be called synchronously, in the order they were bound. By default, a handler stops propagating to the next handler, unless it explicitly returns true.

quill.keyboard.addBinding({ key: 'Tab' }, function(range) {
// I will normally prevent handlers of the tab key
// Return true to let later handlers be called
return true;
});

注意:由于 Quill 的默认处理程序是在初始化时添加的,因此阻止它们的唯一方法是在 configuration 中添加你自己的处理程序。

¥Note: Since Quill's default handlers are added at initialization, the only way to prevent them is to add yours in the configuration.

上下文

¥Context

上下文可以进一步指定仅在特定场景下调用的处理程序。无论是否指定了 context,都会为所有处理程序提供一个 context 对象作为第二个参数。

¥Contexts enable further specification for handlers to be called only in particular scenarios. Regardless if context is specified, a context object is provided as a second parameter for all handlers.

// If the user hits backspace at the beginning of list or blockquote,
// remove the format instead delete any text
quill.keyboard.addBinding({ key: 'Backspace' }, {
collapsed: true,
format: ['blockquote', 'list'],
offset: 0
}, function(range, context) {
if (context.format.list) {
this.quill.format('list', false);
} else {
this.quill.format('blockquote', false);
}
});

collapsed

如果为 true,则仅当用户的选择处于折叠状态(即光标状态)时调用处理程序。如果为 false,则用户的选择长度必须非零,例如用户高亮文本时。

¥If true, handler is called only if the user's selection is collapsed, i.e. in cursor form. If false, the users's selection must be non-zero length, such as when the user has highlighted text.

empty

如果为 true,则仅当用户的选择位于空行时调用;如果为非空行,则调用 false。请注意,将 empty 设置为 true 意味着 collat​​ed 也为 true 且 offset 为 0 - 否则用户的选择不会位于空行。

¥If true, called only if user's selection is on an empty line, false for a non-empty line. Note setting empty to be true implies collapsed is also true and offset is 0—otherwise the user's selection would not be on an empty line.

// If the user hits enter on an empty list, remove the list instead
quill.keyboard.addBinding({ key: 'Enter' }, {
empty: true, // implies collapsed: true and offset: 0
format: ['list']
}, function(range, context) {
this.quill.format('list', false);
});

format

当数组为数组时,如果任何指定的格式处于活动状态,则会调用处理程序。当对象为对象时,必须满足所有指定的格式条件。无论哪种情况,context 参数的 format 属性都将是一个包含所有当前活动格式的对象,与 quill.getFormat() 返回的格式相同。

¥When an Array, handler will be called if any of the specified formats are active. When an Object, all specified formats conditions must be met. In either case, the format property of the context parameter will be an Object of all current active formats, the same returned by quill.getFormat().

const context = {
format: {
list: true, // must be on a list, but can be any value
script: 'super', // must be exactly 'super', 'sub' will not suffice
link: false // cannot be in any link
}
};

offset

仅当用户的选择从行首开始 offset 个字符时,才会调用处理程序。请注意,这是在应用可打印键之前。这与其他上下文规范结合使用时很有用。

¥Handler will be only called when the user's selection starts offset characters from the beginning of the line. Note this is before printable keys have been applied. This is useful in combination with other context specifications.

prefix

必须与用户所选内容起始位置之前的文本匹配的正则表达式。文本不会跨格式边界匹配。提供的 context.prefix 值将是紧接在前的整个文本,而不仅仅是正则表达式匹配。

¥Regex that must match the text immediately preceding the user's selection's start position. The text will not match cross format boundaries. The supplied context.prefix value will be the entire immediately preceding text, not just the regex match.

// When the user types space...
quill.keyboard.addBinding({ key: ' ' }, {
collapsed: true,
format: { list: false }, // ...on a line that's not already a list
prefix: /^-$/, // ...following a '-' character
offset: 1, // ...at the 1st position of the line,
// otherwise handler would trigger if the user
// typed hyphen+space mid sentence
}, function(range, context) {
// the space character is consumed by this handler
// so we only need to delete the hyphen
this.quill.deleteText(range.index - 1, 1);
// apply bullet formatting to the line
this.quill.formatLine(range.index, 1, 'list', 'bullet');
// restore selection
this.quill.setSelection(range.index - 1);
// console.log(context.prefix) would print '-'
});

suffix

prefix 相同,但匹配的是紧跟在用户选择结束位置之后的文本。

¥The same as prefix except matching text immediately following the user's selection's end position.

配置

¥Configuration

默认情况下,Quill 自带了一些实用的按键绑定,例如使用制表符缩进列表。你可以在初始化时添加自己的格式。

¥By default, Quill comes with several useful key bindings, for example indenting lists with tabs. You can add your own upon initialization.

某些绑定对于防止危险的浏览器默认设置至关重要,例如 Enter 键和 Backspace 键。你无法移除这些绑定来恢复到原生浏览器的行为。但是,由于配置中指定的绑定将在 Quill 的默认绑定之前运行,因此你可以处理特殊情况,并在其他情况下将其传递到 Quill。

¥Some bindings are essential to preventing dangerous browser defaults, such as the enter and backspace keys. You cannot remove these bindings to revert to native browser behaviors. However since bindings specified in the configuration will run before Quill's defaults, you can handle special cases and propagate to Quill's otherwise.

添加 quill.keyboard.addBinding 绑定不会在 Quill 绑定之前运行,因为默认绑定届时已经添加。

¥Adding a binding with quill.keyboard.addBinding will not run before Quill's because the defaults bindings will have been added by that point.

每个绑定配置必须包含 keyhandler 选项,并且可以选择包含任何 context 选项。

¥Each binding config must contain key and handler options, and may optionally include any of the context options.

const bindings = {
// This will overwrite the default binding also named 'tab'
tab: {
key: 9,
handler: function() {
// Handle tab
}
},
// There is no default binding named 'custom'
// so this will be added without overwriting anything
custom: {
key: ['b', 'B'],
shiftKey: true,
handler: function(range, context) {
// Handle shift+b
}
},
list: {
key: 'Backspace',
format: ['list'],
handler: function(range, context) {
if (context.offset === 0) {
// When backspace on the first character of a list,
// remove the list instead
this.quill.format('list', false, Quill.sources.USER);
} else {
// Otherwise propogate to Quill's default
return true;
}
}
}
};
const quill = new Quill('#editor', {
modules: {
keyboard: {
bindings: bindings
}
}
});

性能

¥Performance

与 DOM 事件类似,Quill 的按键绑定会在每次匹配时阻塞调用,因此为非常常见的按键绑定设置非常昂贵的处理程序并非明智之举。应用与附加常见阻塞 DOM 事件(例如 scrollmousemove)相同的性能最佳实践。

¥Like DOM events, Quill key bindings are blocking calls on every match, so it is a bad idea to have a very expensive handler for a very common key binding. Apply the same performance best practices as you would when attaching to common blocking DOM events, like scroll or mousemove.