0

DraftJsWYSWYG一起使用:我需要在工具栏中创建一个自定义按钮。单击按钮时,一些自定义 HTML(包括<button>)会添加到内容本身。

我知道如何添加自定义按钮,文档在那里。按钮被添加并且 onclick 我调用定义的方法insertText。但是使用insertText(draft.js 的 DraftModifier 类中的一个方法)它似乎只是将我的 HTML 代码添加为字符串。我应该使用其他方法将自定义 HTML 添加到内容中吗?我想添加真正的 HTML。

这是 TS 声明:

  static insertText(
    contentState: ContentState,
    targetRange: SelectionState,
    text: string,
    inlineStyle?: DraftInlineStyle,
    entityKey?: string
  ): ContentState;
4

2 回答 2

1

您可以使用replaceWithFragment。要构建要插入的片段,首先使用实用程序将字符串转换为 HTML 块convertFromHTML

    const htmlContent = convertFromHTML(text);

然后,使用另一个实用程序将内容块数组传递给地图

    const htmlContentMap = BlockMapBuilder.createFromArray(
      htmlContent.contentBlocks
    );

replaceWithFragment以与您调用相同的方式调用insertText,但使用您构建的 HTML 内容的映射

    const newContent = Modifier.replaceWithFragment(
      currentContent,
      currentSelection,
      htmlContentMap
    );

更新

DraftJS 默认不支持按钮标签,但您可以将其添加为自定义块渲染

首先,通过将默认支持的标签与按钮标签合并来创建类型映射

import {
...
  DefaultDraftBlockRenderMap,
...
} from "draft-js";

...
const mapWithButton = Map({
  button: {
    element: "button"
  }
}).merge(DefaultDraftBlockRenderMap);
...

并将其作为第三个参数传递给convertFromHTML函数

    const htmlContent = convertFromHTML(
      text,
      undefined,
      mapWithButton
    );

创建自定义块渲染器函数并将其传递给编辑器

function myBlockRenderer(contentBlock: ContentBlock) {
  const type = contentBlock.getType();
  if (type === "button") {
    return {
      component: () => {
        return (
          <button onClick={() => console.log("doesn't seem to work :(")}>
            {contentBlock.getText()}
          </button>
        );
      },
      editable: false,
    };
  }
}
...
          <Editor
            ...
            customBlockRenderFunc={myBlockRenderer}
          />

它之所以起作用,是因为它显示了按钮,尽管有时当您插入它的点之前有文本时,它会将先前的文本与按钮文本合并而不显示按钮。点击也不起作用,可能是因为这个

如果您的自定义块渲染器需要鼠标交互,通常明智的做法是在此交互期间临时将您的编辑器设置为 readOnly={true}。这样,用户在与自定义块交互时不会触发编辑器内的任何选择更改。

https://codesandbox.io/s/insert-html-draftjs-73rmc?file=/src/Editor.tsx

于 2021-11-07T20:46:07.303 回答
0

在react-draft-wysiwyg的文档中,有一个使用 html 的专用部分,如下所示。基本步骤是:

  1. 使用将 html 转换为 Draft.js 的库ContentBlock
  2. ContentState用那个初始化 Draft.js ContentBlock
  3. ContentEditor用它初始化 Draft.jsContentState
  4. 使用该对象设置 react-draft-wysiwyg's EditoreditorStateContentEditor

这里有两个活生生的例子来实现这一点:1 , 2

来自react-draft-wysiwyg文档的引用:

Draftjs-to-html可用于转换RawDraftContentState为 html。
html-to-draftjs提供了将 react-draft-wysiwyg 生成的 HTML 转换回ContentState可用于初始化编辑器的 draftJS 的选项。

import React, { Component } from 'react';
import { EditorState, convertToRaw, ContentState } from 'draft-js';
import { Editor } from 'react-draft-wysiwyg';
import draftToHtml from 'draftjs-to-html';
import htmlToDraft from 'html-to-draftjs';
 
class EditorConvertToHTML extends Component {
 constructor(props) {
   super(props);
   const html = '<p>Hey this <strong>editor</strong> rocks </p>';
  const contentBlock = htmlToDraft(html);
  if (contentBlock) {
    const contentState = ContentState.createFromBlockArray(contentBlock.contentBlocks);
    const editorState = EditorState.createWithContent(contentState);
    this.state = {
      editorState,
    };
  }
}

onEditorStateChange: Function = (editorState) => {
  this.setState({
    editorState,
  });
};

render() {
  const { editorState } = this.state;
  return (
    <div>
      <Editor
        editorState={editorState}
         wrapperClassName="demo-wrapper"
        editorClassName="demo-editor"
        onEditorStateChange={this.onEditorStateChange}
      />
      <textarea
        disabled
        value={draftToHtml(convertToRaw(editorState.getCurrentContent()))}
      />
    </div>
  );
}
}
于 2021-11-05T13:37:20.630 回答