如何在Draft-JS中添加链接(无插件)

Ili*_*Ili 1 rich-text-editor reactjs draftjs

我正在尝试创建一个按钮,onClick 将为您提供放置链接的选项,然后该链接必须在文本字段中显示为标签。到目前为止,我设法添加并显示纯文本,但我不知道如何将其转换为标签。

// Link function
  const addLinkFn = (editorState, link) => {
    const contentState = editorState.getCurrentContent();
    const contentStateWithEntity = contentState.createEntity(
      "LINK",
      "IMMUTABLE",
      { url: link }
    );
    const entityKey = contentStateWithEntity.getLastCreatedEntityKey();
    const newEditorState = EditorState.set(editorState, {
      currentContent: contentStateWithEntity,
    });
    return AtomicBlockUtils.insertAtomicBlock(newEditorState, entityKey, link);
  };

  const onAddLink = () => {
    let link = window.prompt("Add link http:// ");
    const newEditorState = addLinkFn(editorState, link);
    setEditorState(newEditorState);
  };
Run Code Online (Sandbox Code Playgroud)

我知道在某个地方我必须有一个像这样的“装饰器”和“策略”:

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

const Link = (props) => {
  const { contentState, entityKey } = props;
  const { url } = contentState.getEntity(entityKey).getData();
  return (
    <a
      className="link"
      href={url}
      rel="noopener noreferrer"
      target="_blank"
      aria-label={url}
    >
      {props.children}
    </a>
  );
};
Run Code Online (Sandbox Code Playgroud)

然后像这样声明它们:

decorators: [
    {
      strategy: linkStrategy,
      component: Link,
    },
  ],
Run Code Online (Sandbox Code Playgroud)

只是我不知道如何将所有内容放在一起以使其正常工作:D 谢谢!

Ili*_*Ili 9

我想到了。整个组件如下所示:

//Add Link Component
import React from "react";
import { CompositeDecorator, EditorState, Modifier } from "draft-js";

const Link = ({ entityKey, contentState, children }) => {
    let { url } = contentState.getEntity(entityKey).getData();
    return (
        <a
            style={{ color: "blue", fontStyle: "italic" }}
            href={url}
            target="_blank"
        >
            {children}
        </a>
    );
};

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

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

// call all together
export const onAddLink = (editorState, setEditorState) => {
    let linkUrl = window.prompt("Add link http:// ");
    const decorator = createLinkDecorator();
    if (linkUrl) {
        let displayLink = window.prompt("Display Text");
        if (displayLink) {
            const currentContent = editorState.getCurrentContent();
            const createEntity = currentContent.createEntity("LINK", "MUTABLE", {
                url: linkUrl,
            });
            let entityKey = currentContent.getLastCreatedEntityKey();
            const selection = editorState.getSelection();
            const textWithEntity = Modifier.insertText(
                currentContent,
                selection,
                displayLink,
                null,
                entityKey
            );
            let newState = EditorState.createWithContent(textWithEntity, decorator);
            setEditorState(newState);
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

然后您必须将其附加到编辑器工具栏(如果有的话:

//Add Link Component
import React from "react";
import { CompositeDecorator, EditorState, Modifier } from "draft-js";

const Link = ({ entityKey, contentState, children }) => {
    let { url } = contentState.getEntity(entityKey).getData();
    return (
        <a
            style={{ color: "blue", fontStyle: "italic" }}
            href={url}
            target="_blank"
        >
            {children}
        </a>
    );
};

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

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

// call all together
export const onAddLink = (editorState, setEditorState) => {
    let linkUrl = window.prompt("Add link http:// ");
    const decorator = createLinkDecorator();
    if (linkUrl) {
        let displayLink = window.prompt("Display Text");
        if (displayLink) {
            const currentContent = editorState.getCurrentContent();
            const createEntity = currentContent.createEntity("LINK", "MUTABLE", {
                url: linkUrl,
            });
            let entityKey = currentContent.getLastCreatedEntityKey();
            const selection = editorState.getSelection();
            const textWithEntity = Modifier.insertText(
                currentContent,
                selection,
                displayLink,
                null,
                entityKey
            );
            let newState = EditorState.createWithContent(textWithEntity, decorator);
            setEditorState(newState);
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

然后在编辑器的显示部分引用 deocrator,以便它知道链接的样子:

import { onAddLink } from "./Link";  
<button
    onClick={() => onAddLink(props.editorState, props.setEditorState)}
>
    link
</button>
Run Code Online (Sandbox Code Playgroud)