Draft.js 使用 applyEntity 添加超链接似乎不起作用

Draft.js adding hyperlink using applyEntity doesn't seem to work

我已经研究这个问题一段时间了,希望这不是一个错误。

我正在使用 Draft.js 测试一个文本编辑器,我只是希望我的用户在他们的文章中添加一个 hyperlink,所以我创建了一个函数来实现它修改编辑器状态的内容。

const addLlink = (e) => {
    e.preventDefault();
    const contentState = editorState.getCurrentContent();
    const contentStateWithEntity = contentState.createEntity(
        'LINK', 'MUTABLE', {url: 'https://www.amazon.com'} // link for testing only
    );
    const entityKey = contentStateWithEntity.getLastCreatedEntityKey();
    const contentStateWithLink = Modifier.applyEntity(
        contentStateWithEntity,
        editorState.getSelection(),
        entityKey
    );
    // tried with and without styling
    const styledContentStateWithLink = Modifier.applyInlineStyle(
        contentStateWithLink,
        editorState.getSelection(),
        'HYPERLINK'
    );
    const newState = EditorState.set(editorState, {
        currentContent: styledContentStateWithLink
    });

    setEditorState(newState);
    // Also tried: setEditorState(RichUtils.toggleLink(newState, newState.getSelection(), entityKey));
}

当我触发它时,我只使用一个 Evergreen-ui 按钮:

<Button onMouseDown={addLlink} appearance="minimal">Link</Button>

我使用 Modifier 对象实现的样式有效,但我似乎无法使 link 实际起作用。应该注意的是,link 插件作为一个包,效果很好,但这仅用于检测键入的 out/pasted URL(未嵌入到文本中)。

对于 link 使用 React 函数式编程的人,有没有人有实际工作示例或我可能做错的建议?

事实证明,我需要添加装饰器才能检测到实体。我放置了我的编辑器组件的代码 above/outside:

const findLinkEntities = (contentBlock, callback, contentState) => {
contentBlock.findEntityRanges(
  (character) => {
    const entityKey = character.getEntity();
    return (
      entityKey !== null &&
      contentState.getEntity(entityKey).getType() === 'LINK'
    );
  },
  callback
);


}
const Link = (props) => {
    const {url} = props.contentState.getEntity(props.entityKey).getData();
    return (
      <a href={url} >
        {props.children}
      </a>
    );
};

const strategyDecorator = new CompositeDecorator([
    {
      strategy: findLinkEntities,
      component: Link,
    },
]);

基本上,它会检测 link 个实体,并在您使用 EditorState 设置新内容时将它们转换为元素:

const newState = EditorState.set(editorState, {
        currentContent: styledContentStateWithLink,
        decorator: strategyDecorator
    });

根据 official example 你需要添加一个装饰器来找到实体并应用 Link 组件

const decorator = new CompositeDecorator([
  {
    strategy: findLinkEntities,
    component: Link,
  },
]);

并且当您使用 linkify 插件时,您必须将装饰器传递给插件编辑器

import Editor from "draft-js-plugins-editor";
import createLinkifyPlugin from "draft-js-linkify-plugin";
import "draft-js-linkify-plugin/lib/plugin.css";

...
<Editor
  decorators={[decorator]}
  editorState={editorState}
  onChange={setEditorState}
  plugins={[linkifyPlugin]}
/>
...

您可以在此处查看工作示例 https://codesandbox.io/s/test-selection-decorator-draft-js-link-0lblg?file=/src/ExtendedEditor.js