DraftJs:使用实体键替换实体

joh*_*pin 5 javascript typescript reactjs draftjs

我正在使用Draftjs创建富文本编辑器,但找不到任何资源来帮助我解决问题。

请首先查看代码和

您可以看到包含链接(testtest红色)的文本。如果你点击它,你会在表格中看到链接的一些信息:

|  link src         | http://localhost:8080/testtest |
|  link text        | testtest                       |
|  link Entity key  | ab5a7c6d...                    |
Run Code Online (Sandbox Code Playgroud)

感谢我的getCurrentLinkKey助手,我得到了当前的链接密钥 () :

|  link src         | http://localhost:8080/testtest |
|  link text        | testtest                       |
|  link Entity key  | ab5a7c6d...                    |
Run Code Online (Sandbox Code Playgroud)

然后使用此密钥,我可以Entity使用getCurrentLinkEntityhelper获取链接:

const getCurrentLinkKey = (
  editorState: EditorState,
  contentState?: ContentState
): string => {
  if (contentState === undefined) {
    contentState = editorState.getCurrentContent();
  }

  const startKey = editorState.getSelection().getStartKey();
  const startOffset = editorState.getSelection().getStartOffset();
  const blockWithLinkAtBeginning = contentState.getBlockForKey(startKey);

  return blockWithLinkAtBeginning.getEntityAt(startOffset);
};
Run Code Online (Sandbox Code Playgroud)

使用链接Entity我终于可以得到srctext值:

const getCurrentLinkEntity = (
  editorState: EditorState
): EntityInstance | null => {
  const contentState = editorState.getCurrentContent();
  const linkKey = getCurrentLinkKey(editorState, contentState);

  if (linkKey) {
    return contentState.getEntity(linkKey);
  }

  return null;
};
Run Code Online (Sandbox Code Playgroud)

您可以在底部看到一个按钮Insert link。如果您选择整个链接testtest并单击此按钮,该链接将被替换。

此功能由insertLink帮助程序处理:

getCurrentLinkEntity(editorState).getData().url   // 
getCurrentLinkEntity(editorState).getData().text  // 
Run Code Online (Sandbox Code Playgroud)

但此功能只会用谷歌链接替换您选择的文本。我想要的是,如果您在链接上单击按钮,则应该更新整个链接。所以我创建了replaceLink助手:

const insertLink = (
  link: string,
  text: string,
  editorState: EditorState,
  setEditorState: (editorState: EditorState) => void
): void => {
  const contentStateWithEntity = editorState
    .getCurrentContent()
    .createEntity("LINK", "MUTABLE", { url: link, text });

  const entityKey = contentStateWithEntity.getLastCreatedEntityKey();

  const contentState = Modifier.replaceText(
    editorState.getCurrentContent(),
    editorState.getSelection(),
    text,
    editorState.getCurrentInlineStyle(),
    entityKey
  );

  const newEditorState = EditorState.set(editorState, {
    currentContent: contentStateWithEntity
  });
  const newEditorStateWithLink = RichUtils.toggleLink(
    newEditorState,
    newEditorState.getSelection(),
    entityKey
  );

  setEditorState(
    EditorState.push(newEditorStateWithLink, contentState, "insert-characters")
  );
};
Run Code Online (Sandbox Code Playgroud)

但可悲的是,如果我点击Replace link按钮(即触发replaceLink助手),链接不更新,但srctext是空的:

|  link src         |             |
|  link text        |             |
|  link Entity key  | a1e34047... |
Run Code Online (Sandbox Code Playgroud)

所以作为一个想法,我可以如何Entity使用它的实体键替换链接?

joh*_*pin 1

好吧,我给出了一个答案,它使用Draftjs-utils包并替换链接,但不使用其实体键

这个助手的灵感来自于react-draft-wysiwygreplaceLink库的工作:

export const replaceLink = (
  link: string,
  text: string,
  editorState: EditorState,
  setEditorState: (editorState: EditorState) => void
): void => {
  const currentContent = editorState.getCurrentContent();

  // Create new link entity
  const contentStateWithEntity = currentContent.createEntity(
    "LINK",
    "MUTABLE",
    { url: link, text }
  );

  // Get created link entity's key
  const entityKey = contentStateWithEntity.getLastCreatedEntityKey();

  let selection = editorState.getSelection();

  const entityRange = getEntityRange(
    editorState,
    getSelectionEntity(editorState)
  );

  const isBackward = selection.getIsBackward();

  if (isBackward) {
    selection = selection.merge({
      anchorOffset: entityRange.end,
      focusOffset: entityRange.start
    });
  } else {
    selection = selection.merge({
      anchorOffset: entityRange.start,
      focusOffset: entityRange.end
    });
  }

  const updatedEditorWithText = Modifier.replaceText(
    currentContent,
    selection,
    text,
    editorState.getCurrentInlineStyle(),
    entityKey
  );

  const newEditorState = EditorState.push(
    editorState,
    updatedEditorWithText,
    "insert-characters"
  );

  setEditorState(
    EditorState.push(newEditorState, updatedEditorWithText, "insert-characters")
  );
};
Run Code Online (Sandbox Code Playgroud)

检查代码和框以查看实时情况。