handleKeyCommand - "space" 的默认回退功能不起作用
handleKeyCommand - default fallback function for "space" is not working
需要的场景:键入单词后跟解析单词,如果匹配预定义缩写列表则自动替换。
实现方式:自定义 keyBindingFn 属性 其中 space 创建自定义命令 "cc-space"。 handleKeyCommand 事件识别 "cc-space",评估最后输入的单词并执行上述功能。
错误:当文档中建议不匹配 handleKeyCommand returns "not-handled" 以允许 "default command" 时,这似乎被忽略为编辑器当其他一切都按预期工作时,从不在让通时插入 space。
import React from "react"
import { Editor, EditorState, SelectionState, Modifier, getDefaultKeyBinding, KeyBindingUtil } from "draft-js"
const myKeyBindingFn = event => {
const { hasCommandModifier } = KeyBindingUtil
if (event.keyCode === 32 && !hasCommandModifier(event)) {
return "cc-space"
}
return getDefaultKeyBinding(event)
}
export default class Note extends React.Component {
constructor(props) {
super(props)
this.state = { editorState: EditorState.createEmpty() }
this.onChange = this.onChange.bind(this)
this.handleBeforeInput = this.handleBeforeInput.bind(this)
this.handleKeyCommand = this.handleKeyCommand.bind(this)
}
onChange(editorState) {
this.setState({ editorState })
}
handleBeforeInput(chars, editorState) {
this.setState({ editorState })
}
handleKeyCommand(command, editorState) {
console.log("command", command)
if (command === "cc-space") {
const selectionState = editorState.getSelection()
const anchorKey = selectionState.getAnchorKey()
const contentState = editorState.getCurrentContent()
const currentContentBlock = contentState.getBlockForKey(anchorKey)
const lastWordEntered = currentContentBlock.getText()
if (lastWordEntered === "hml") {
const selectionWord = new SelectionState({
anchorKey: currentContentBlock.getKey(),
anchorOffset: 0,
focusKey: currentContentBlock.getKey(),
focusOffset: lastWordEntered.length
})
const newContentState = Modifier.replaceText(contentState, selectionWord, "heimilislæknir ")
const nextEditorState = EditorState.push(editorState, newContentState, "insert-characters") // editorState.getLastChangeType()
this.setState({ editorState: nextEditorState }, this.focus)
return "handled"
}
}
return "not-handled"
}
render() {
return (
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
handleBeforeInput={this.handleBeforeInput}
handleKeyCommand={this.handleKeyCommand}
keyBindingFn={myKeyBindingFn}
spellCheck={false}
autocorrect="off"
/>
)
}
}
当您使用自定义按键绑定功能myKeyBindingFn
时,您应该为该自定义事件提供自定义逻辑。
例如,如果您从 myKeyBindingFn
中删除 return "cc-space"
,space 将正常工作。
因此,当用户输入 space:
时,您可以定义自己的逻辑
import React from "react";
import {
Editor,
EditorState,
SelectionState,
Modifier,
getDefaultKeyBinding,
KeyBindingUtil
} from "draft-js";
const myKeyBindingFn = event => {
const { hasCommandModifier } = KeyBindingUtil;
if (event.keyCode === 32 && !hasCommandModifier(event)) {
return "cc-space";
}
return getDefaultKeyBinding(event);
};
export default class Note extends React.Component {
constructor(props) {
super(props);
this.state = { editorState: EditorState.createEmpty() };
this.onChange = this.onChange.bind(this);
this.handleBeforeInput = this.handleBeforeInput.bind(this);
this.handleKeyCommand = this.handleKeyCommand.bind(this);
}
onChange(editorState) {
this.setState({ editorState });
}
handleBeforeInput(chars, editorState) {
this.setState({ editorState });
}
handleKeyCommand(command, editorState) {
console.log("command", command);
if (command === "cc-space") {
const selectionState = editorState.getSelection();
const anchorKey = selectionState.getAnchorKey();
const contentState = editorState.getCurrentContent();
const currentContentBlock = contentState.getBlockForKey(anchorKey);
const lastWordEntered = currentContentBlock.getText();
if (lastWordEntered === "hml") {
const selectionWord = new SelectionState({
anchorKey: currentContentBlock.getKey(),
anchorOffset: 0,
focusKey: currentContentBlock.getKey(),
focusOffset: lastWordEntered.length
});
const newContentState = Modifier.replaceText(
contentState,
selectionWord,
"heimilislæknir "
);
const nextEditorState = EditorState.push(
editorState,
newContentState,
"insert-characters"
); // editorState.getLastChangeType()
this.setState({ editorState: nextEditorState }, this.focus);
return "handled";
} else {
// There are no any matches.
// We have to implement custom logic to space:
const newContentState = Modifier.insertText(
contentState,
selectionState,
" "
);
const nextEditorState = EditorState.push(
editorState,
newContentState,
"insert-characters"
);
this.setState({ editorState: nextEditorState });
}
}
return "not-handled";
}
render() {
return (
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
handleBeforeInput={this.handleBeforeInput}
handleKeyCommand={this.handleKeyCommand}
keyBindingFn={myKeyBindingFn}
spellCheck={false}
autocorrect="off"
/>
);
}
}
您也可以 return cc-space
仅在必要时才触发事件,而不是实施自定义逻辑来插入 space 字符:
import React from "react";
import {
Editor,
EditorState,
SelectionState,
Modifier,
getDefaultKeyBinding,
KeyBindingUtil
} from "draft-js";
export default class Note extends React.Component {
constructor(props) {
super(props);
this.state = { editorState: EditorState.createEmpty() };
this.onChange = this.onChange.bind(this);
this.handleBeforeInput = this.handleBeforeInput.bind(this);
this.handleKeyCommand = this.handleKeyCommand.bind(this);
}
// we move this method to class, becouse we have to get this.state.editorState to recognize the last word
myKeyBindingFn = event => {
const { hasCommandModifier } = KeyBindingUtil;
if (event.keyCode === 32 && !hasCommandModifier(event)) {
const selectionState = this.state.editorState.getSelection();
const anchorKey = selectionState.getAnchorKey();
const contentState = this.state.editorState.getCurrentContent();
const currentContentBlock = contentState.getBlockForKey(anchorKey);
const lastWordEntered = currentContentBlock.getText();
if (lastWordEntered === "hml") {
// return cc-space only if it's necessary
return "cc-space";
}
}
// in any other cases we return defaultKeyBinding
return getDefaultKeyBinding(event);
};
onChange(editorState) {
this.setState({ editorState });
}
handleBeforeInput(chars, editorState) {
this.setState({ editorState });
}
handleKeyCommand(command, editorState) {
console.log("command", command);
if (command === "cc-space") {
const selectionState = editorState.getSelection();
const anchorKey = selectionState.getAnchorKey();
const contentState = editorState.getCurrentContent();
const currentContentBlock = contentState.getBlockForKey(anchorKey);
const lastWordEntered = currentContentBlock.getText();
if (lastWordEntered === "hml") {
const selectionWord = new SelectionState({
anchorKey: currentContentBlock.getKey(),
anchorOffset: 0,
focusKey: currentContentBlock.getKey(),
focusOffset: lastWordEntered.length
});
const newContentState = Modifier.replaceText(
contentState,
selectionWord,
"heimilislæknir "
);
const nextEditorState = EditorState.push(
editorState,
newContentState,
"insert-characters"
); // editorState.getLastChangeType()
this.setState({ editorState: nextEditorState }, this.focus);
return "handled";
}
}
return "not-handled";
}
render() {
return (
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
handleBeforeInput={this.handleBeforeInput}
handleKeyCommand={this.handleKeyCommand}
keyBindingFn={this.myKeyBindingFn}
spellCheck={false}
autocorrect="off"
/>
);
}
}
P.S。 lastWordEntered
包含整个文本,而不是输入的单词。也许,你只想得到一个词——你可以从这里得到解决方案 https://github.com/facebook/draft-js/issues/506
需要的场景:键入单词后跟解析单词,如果匹配预定义缩写列表则自动替换。
实现方式:自定义 keyBindingFn 属性 其中 space 创建自定义命令 "cc-space"。 handleKeyCommand 事件识别 "cc-space",评估最后输入的单词并执行上述功能。
错误:当文档中建议不匹配 handleKeyCommand returns "not-handled" 以允许 "default command" 时,这似乎被忽略为编辑器当其他一切都按预期工作时,从不在让通时插入 space。
import React from "react"
import { Editor, EditorState, SelectionState, Modifier, getDefaultKeyBinding, KeyBindingUtil } from "draft-js"
const myKeyBindingFn = event => {
const { hasCommandModifier } = KeyBindingUtil
if (event.keyCode === 32 && !hasCommandModifier(event)) {
return "cc-space"
}
return getDefaultKeyBinding(event)
}
export default class Note extends React.Component {
constructor(props) {
super(props)
this.state = { editorState: EditorState.createEmpty() }
this.onChange = this.onChange.bind(this)
this.handleBeforeInput = this.handleBeforeInput.bind(this)
this.handleKeyCommand = this.handleKeyCommand.bind(this)
}
onChange(editorState) {
this.setState({ editorState })
}
handleBeforeInput(chars, editorState) {
this.setState({ editorState })
}
handleKeyCommand(command, editorState) {
console.log("command", command)
if (command === "cc-space") {
const selectionState = editorState.getSelection()
const anchorKey = selectionState.getAnchorKey()
const contentState = editorState.getCurrentContent()
const currentContentBlock = contentState.getBlockForKey(anchorKey)
const lastWordEntered = currentContentBlock.getText()
if (lastWordEntered === "hml") {
const selectionWord = new SelectionState({
anchorKey: currentContentBlock.getKey(),
anchorOffset: 0,
focusKey: currentContentBlock.getKey(),
focusOffset: lastWordEntered.length
})
const newContentState = Modifier.replaceText(contentState, selectionWord, "heimilislæknir ")
const nextEditorState = EditorState.push(editorState, newContentState, "insert-characters") // editorState.getLastChangeType()
this.setState({ editorState: nextEditorState }, this.focus)
return "handled"
}
}
return "not-handled"
}
render() {
return (
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
handleBeforeInput={this.handleBeforeInput}
handleKeyCommand={this.handleKeyCommand}
keyBindingFn={myKeyBindingFn}
spellCheck={false}
autocorrect="off"
/>
)
}
}
当您使用自定义按键绑定功能myKeyBindingFn
时,您应该为该自定义事件提供自定义逻辑。
例如,如果您从 myKeyBindingFn
中删除 return "cc-space"
,space 将正常工作。
因此,当用户输入 space:
时,您可以定义自己的逻辑import React from "react";
import {
Editor,
EditorState,
SelectionState,
Modifier,
getDefaultKeyBinding,
KeyBindingUtil
} from "draft-js";
const myKeyBindingFn = event => {
const { hasCommandModifier } = KeyBindingUtil;
if (event.keyCode === 32 && !hasCommandModifier(event)) {
return "cc-space";
}
return getDefaultKeyBinding(event);
};
export default class Note extends React.Component {
constructor(props) {
super(props);
this.state = { editorState: EditorState.createEmpty() };
this.onChange = this.onChange.bind(this);
this.handleBeforeInput = this.handleBeforeInput.bind(this);
this.handleKeyCommand = this.handleKeyCommand.bind(this);
}
onChange(editorState) {
this.setState({ editorState });
}
handleBeforeInput(chars, editorState) {
this.setState({ editorState });
}
handleKeyCommand(command, editorState) {
console.log("command", command);
if (command === "cc-space") {
const selectionState = editorState.getSelection();
const anchorKey = selectionState.getAnchorKey();
const contentState = editorState.getCurrentContent();
const currentContentBlock = contentState.getBlockForKey(anchorKey);
const lastWordEntered = currentContentBlock.getText();
if (lastWordEntered === "hml") {
const selectionWord = new SelectionState({
anchorKey: currentContentBlock.getKey(),
anchorOffset: 0,
focusKey: currentContentBlock.getKey(),
focusOffset: lastWordEntered.length
});
const newContentState = Modifier.replaceText(
contentState,
selectionWord,
"heimilislæknir "
);
const nextEditorState = EditorState.push(
editorState,
newContentState,
"insert-characters"
); // editorState.getLastChangeType()
this.setState({ editorState: nextEditorState }, this.focus);
return "handled";
} else {
// There are no any matches.
// We have to implement custom logic to space:
const newContentState = Modifier.insertText(
contentState,
selectionState,
" "
);
const nextEditorState = EditorState.push(
editorState,
newContentState,
"insert-characters"
);
this.setState({ editorState: nextEditorState });
}
}
return "not-handled";
}
render() {
return (
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
handleBeforeInput={this.handleBeforeInput}
handleKeyCommand={this.handleKeyCommand}
keyBindingFn={myKeyBindingFn}
spellCheck={false}
autocorrect="off"
/>
);
}
}
您也可以 return cc-space
仅在必要时才触发事件,而不是实施自定义逻辑来插入 space 字符:
import React from "react";
import {
Editor,
EditorState,
SelectionState,
Modifier,
getDefaultKeyBinding,
KeyBindingUtil
} from "draft-js";
export default class Note extends React.Component {
constructor(props) {
super(props);
this.state = { editorState: EditorState.createEmpty() };
this.onChange = this.onChange.bind(this);
this.handleBeforeInput = this.handleBeforeInput.bind(this);
this.handleKeyCommand = this.handleKeyCommand.bind(this);
}
// we move this method to class, becouse we have to get this.state.editorState to recognize the last word
myKeyBindingFn = event => {
const { hasCommandModifier } = KeyBindingUtil;
if (event.keyCode === 32 && !hasCommandModifier(event)) {
const selectionState = this.state.editorState.getSelection();
const anchorKey = selectionState.getAnchorKey();
const contentState = this.state.editorState.getCurrentContent();
const currentContentBlock = contentState.getBlockForKey(anchorKey);
const lastWordEntered = currentContentBlock.getText();
if (lastWordEntered === "hml") {
// return cc-space only if it's necessary
return "cc-space";
}
}
// in any other cases we return defaultKeyBinding
return getDefaultKeyBinding(event);
};
onChange(editorState) {
this.setState({ editorState });
}
handleBeforeInput(chars, editorState) {
this.setState({ editorState });
}
handleKeyCommand(command, editorState) {
console.log("command", command);
if (command === "cc-space") {
const selectionState = editorState.getSelection();
const anchorKey = selectionState.getAnchorKey();
const contentState = editorState.getCurrentContent();
const currentContentBlock = contentState.getBlockForKey(anchorKey);
const lastWordEntered = currentContentBlock.getText();
if (lastWordEntered === "hml") {
const selectionWord = new SelectionState({
anchorKey: currentContentBlock.getKey(),
anchorOffset: 0,
focusKey: currentContentBlock.getKey(),
focusOffset: lastWordEntered.length
});
const newContentState = Modifier.replaceText(
contentState,
selectionWord,
"heimilislæknir "
);
const nextEditorState = EditorState.push(
editorState,
newContentState,
"insert-characters"
); // editorState.getLastChangeType()
this.setState({ editorState: nextEditorState }, this.focus);
return "handled";
}
}
return "not-handled";
}
render() {
return (
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
handleBeforeInput={this.handleBeforeInput}
handleKeyCommand={this.handleKeyCommand}
keyBindingFn={this.myKeyBindingFn}
spellCheck={false}
autocorrect="off"
/>
);
}
}
P.S。 lastWordEntered
包含整个文本,而不是输入的单词。也许,你只想得到一个词——你可以从这里得到解决方案 https://github.com/facebook/draft-js/issues/506