handleKeyCommand - "space"的默认回退功能不起作用



想要的场景:键入单词后跟解析单词,如果匹配预定义的缩写列表,则自动替换。

实现方式:自定义键绑定Fn属性,其中空间创建自定义命令"cc-space"。 handleKeyCommand 事件识别"cc-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"将正常工作。

因此,您可以在用户进入空间时定义自己的逻辑:

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"
      />
    );
  }
}

此外,仅在必要时才能返回cc-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"
      />
    );
  }
}

附言 lastWordEntered有全文,而不是输入的单词。也许,你只想得到一个词——你可以从这里得到一个解决方案 https://github.com/facebook/draft-js/issues/506

最新更新