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

时间:2018-03-10 18:55:18

标签: reactjs draftjs

通缉情景:输入单词后跟解析单词,如果匹配预定义缩写的列表,则会自动替换。

实现:自定义keyBindingFn属性,其中space创建自定义命令“cc-space”。 handleKeyCommand事件识别“cc-space”,评估最后输入的单词并在上面执行。

错误:当没有匹配的handleKeyCommand按照文档中的建议返回“not-processed”以允许“default command”时,这似乎被忽略,因为编辑器永远不会在let-through上插入空格而其他所有内容按预期工作。

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

1 个答案:

答案 0 :(得分:1)

使用自定义键绑定功能myKeyBindingFn时,应为此自定义事件提供自定义逻辑。

例如,如果从return "cc-space"空格中删除myKeyBindingFn,则可以正常使用。

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

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

此外,只有在必要时才能返回cc-space事件,而不是实现自定义逻辑来插入空格字符:

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

P.S。 lastWordEntered包含全文,而不是输入的单词。也许,你只想得到一个词 - 你可以从这里得到一个解决方案std::set's constructor