我们如何在词法富编辑器中从 editorState 获取 html?

Rup*_*ind 12 lexical reactjs

我想从 Lexical Rich Editor 中的 editorState 生成 HTML 格式,我可以使用 editorState 进行选择,什么最好保存到数据库、HTML 或某种 JSON 格式中?

我想在编辑器之外显示这个 HTML。这是一些代码示例

const onChange = (editorState) => {
  const editorStateTextString = editorState.read(() => {
    const selection = $getSelection();
    
    console.log(selection);

    return $getRoot().getTextContent();
  });

  // TODO: saving text only at the moment
  if (changeHandler) {
    changeHandler(editorStateTextString);
  }
};

<LexicalComposer initialConfig={editorConfig}>
  <div className="editor-container">
    <ToolbarPlugin aditionalTools={aditionalTools} />
    <div className="editor-inner">
      <RichTextPlugin
        contentEditable={<ContentEditable className="editor-input" />}
        placeholder={<Placeholder placeholder={placeholder} />}
      />
      <OnChangePlugin ignoreInitialChange onChange={onChange} />
    </div>
  </div>
</LexicalComposer>
Run Code Online (Sandbox Code Playgroud)

Ste*_*955 13

我遇到了同样的问题并通过使用以下简单的插件解决了它。困难的部分是获得对编辑器的引用,这就是我所使用useLexicalComposerContext()的。

import { useState, useEffect } from "react";
import { OnChangePlugin } from "@lexical/react/LexicalOnChangePlugin";
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
import { $generateHtmlFromNodes, $generateNodesFromDOM } from "@lexical/html";
import { $insertNodes } from "lexical";

interface Props {
    initialHtml?: string;
    onHtmlChanged: (html: string) => void;
}

const HtmlPlugin = ({ initialHtml, onHtmlChanged }: Props) => {
    const [editor] = useLexicalComposerContext();

    const [isFirstRender, setIsFirstRender] = useState(true);

    useEffect(() => {
        if (!initialHtml || !isFirstRender) return;

        setIsFirstRender(false);

        editor.update(() => {
            const parser = new DOMParser();
            const dom = parser.parseFromString(initialHtml, "text/html");
            const nodes = $generateNodesFromDOM(editor, dom);
            $insertNodes(nodes);
        });
    }, []);

    return (
        <OnChangePlugin
            onChange={(editorState) => {
                editorState.read(() => {
                    onHtmlChanged($generateHtmlFromNodes(editor));
                });
            }}
        />
    );
};

export default HtmlPlugin;
Run Code Online (Sandbox Code Playgroud)

你可以像这样使用它LexicalComposer

<LexicalComposer initialConfig={editorConfig}>
  <div className="editor-container">
    <ToolbarPlugin aditionalTools={aditionalTools} />
    <div className="editor-inner">
      <RichTextPlugin
        contentEditable={<ContentEditable className="editor-input" />}
        placeholder={<Placeholder placeholder={placeholder} />}
      />
      {/* see here */}
      <HtmlPlugin
        onHtmlChanged={(html) => console.log(html)}
        initialHtml="<h1>Test</h1><p>Lorem ipsum dolor sit amet</p>"
        />
    </div>
  </div>
</LexicalComposer>
Run Code Online (Sandbox Code Playgroud)


小智 1

您绝对应该将 JSON 保存到数据库中。最重要的是,这让您决定如何渲染它。也许在某些情况下您希望渲染为 HTML,但在其他情况下(例如:移动设备)您希望渲染为原生元素。

要获取 JSON 结构,您可以执行以下操作:

editor.getEditorState().toJSON();
Run Code Online (Sandbox Code Playgroud)

另外,关于你的第二个问题。以下是获取 HTML 的方法:

import {$generateHtmlFromNodes} from '@lexical/html';

...    

const htmlString = $generateHtmlFromNodes(editor, null);
Run Code Online (Sandbox Code Playgroud)

注意:您需要在词法上下文中调用上述方法(即:在回调中,如editor.update