在草稿JS中实现自动完成但没有像"@"这样的"触发器"

Vic*_*tor 17 javascript autocomplete typescript reactjs draftjs

我想实现像标签编辑器这样的东西.但是,它仅仅意味着那些标签,所以我希望用户看到自动完成建议弹出窗口而不必输入类似@#的内容,只需要文本本身.

我有一些有用的东西,但弹出窗口显示在屏幕上的奇怪位置:

  • 当我第一次输入内容并弹出窗口时,它出现在屏幕左上角附近
  • 在创建第一个实体后,当按下SPACE并再次开始输入时,弹出窗口会从它的直观位置(即在单词的第一个字母下方)右侧出现几个像素

这是一个众所周知的编辑器的例子(虽然没有用草稿实现),所以你可以更好地理解我想要实现的内容.

Gmail电子邮件编辑器

首先,这是触发建议弹出窗口的函数:

private onChange(editorState: EditorState) {
  const content = editorState.getCurrentContent();
  const selection = editorState.getSelection();
  const currentBlock = content.getBlockForKey(selection.getAnchorKey());

  if (selection.isCollapsed()) {
    const blockText = currentBlock.getText();
    const wordMeta = getWordAt(blockText, selection.getAnchorOffset());
    const categoryRegex = /([\w]*)/;
    const matches = wordMeta.word.match(categoryRegex);
    const existingEntity = currentBlock.getEntityAt(wordMeta.begin);

    if (!existingEntity && matches) {
      const categorySearch = matches[1];
      const selection = window.getSelection();
      if (this.state.autoComplete.search !== categorySearch && selection.rangeCount > 0) {
        const range = selection.getRangeAt(0);
        const boundingRect = getRangeBoundingClientRect(range);

        this.setState((prevState: StateType) => {
          let state = {
            autoComplete: {
              active: true,
              search: categorySearch,
              searchMeta: {
                begin: wordMeta.begin,
                end: wordMeta.end,
              },
            },
            selectionRect: prevState.selectionRect,
          };

          if (prevState.autoComplete.active === false) {
            state.selectionRect = boundingRect;
          }

          return state;
        });
      }
    }
  }

  this.props.onChange(editorState);
}
Run Code Online (Sandbox Code Playgroud)

这是getWordAt功能:

function getWordAt(text: string, pos: number): WordMeta
{
  const left = text.slice(0, pos + 1).search(/\S+$/);
  const right = text.slice(pos).search(/\s/);

  if (right < 0) {
    return {
      word: text.slice(left),
      begin: left,
      end: text.length,
    };
  }

  return {
    word: text.slice(left, right + pos),
    begin: left,
    end: right + pos,
  };
}
Run Code Online (Sandbox Code Playgroud)

什么是更好的方式来处理弹出窗口的位置,甚至可能是这种自动完成的策略?谢谢!

Var*_*sha 1

相反draft-js-typeahead- TypeaheadEditor 是一个包装草稿编辑器的反应组件。您可以使用 满足要求的React-Autosuggest组件。它具有可与 React 元素原生配合使用的自定义渲染。它速度很快并且很容易定制。完全控制建议呈现。

我们可以让它处理 JS 对象而不是普通字符串。

  1. propsonSuggestionSelected是获取所选建议的回调
  2. suggestionRenderer方法接受建议并返回 React 标记

查看React-Autosuggest

您可以通过使用自定义块渲染器来使用上述组件,可以在编辑器的框架内引入复杂的丰富交互。

你必须绞尽脑汁才能实现你想要的目标,这并不简单。这是我的建议,通过它你可以实现它,但它并不那么容易。