首页 > 解决方案 > 如何在 Draft-JS 中添加链接(无插件)

问题描述

我正在尝试创建一个按钮,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);
  };

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

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>
  );
};

然后像这样声明它们:

decorators: [
    {
      strategy: linkStrategy,
      component: Link,
    },
  ],

只是我不确定如何将所有东西放在一起以使其正常工作:D 谢谢!

标签: reactjsrich-text-editordraftjs

解决方案


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

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

然后你必须将它附加到编辑器工具栏(如果你有一个:

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

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

import { createLinkDecorator } from "./Components/Link"; 
const decorator = createLinkDecorator();
const editorState = props.postData
    ? EditorState.createWithContent(convertFromRaw(props.postData), 
        // add the decorator after the state
        decorator
    )
    : EditorState.createEmpty();

推荐阅读