PlateJS HTML序列化问题:点击按钮无法获取有效HTML字符串
问题解决:Plate编辑器获取HTML并集成React-Hook-Form
问题原因
你当前代码里的html变量是组件初始化时计算的,此时编辑器内容还未更新,后续编辑操作不会重新计算这个变量,所以点击按钮输出的始终是初始的空字符串。正确的做法是在需要获取HTML的时机(比如点击按钮、表单提交)实时调用serializeHtml,基于最新的编辑器内容生成HTML。
修正后的基础版本代码
"use client"; import { plugins } from "@/lib/plugins"; import { CommentsProvider } from "@udecode/plate-comments"; import { Plate, createPlateEditor } from "@udecode/plate-common"; import { serializeHtml } from "@udecode/plate-serializer-html"; import { FC } from "react"; import { DndProvider } from "react-dnd"; import { HTML5Backend } from "react-dnd-html5-backend"; import { CommentsPopover } from "@/components/plate-ui/comments-popover"; import { Editor } from "@/components/plate-ui/editor"; import { FixedToolbar } from "@/components/plate-ui/fixed-toolbar"; import { FixedToolbarButtons } from "@/components/plate-ui/fixed-toolbar-buttons"; import { FloatingToolbar } from "@/components/plate-ui/floating-toolbar"; import { FloatingToolbarButtons } from "@/components/plate-ui/floating-toolbar-buttons"; import { MentionCombobox } from "@/components/plate-ui/mention-combobox"; interface PropsType { initialValue?: any; } const RichTextEditor: FC<PropsType> = ({ initialValue }) => { const editor = createPlateEditor({ plugins }); const handleGetHtml = () => { // 点击时实时生成HTML const html = serializeHtml(editor, { nodes: editor.children, dndWrapper: (props) => <DndProvider backend={HTML5Backend} {...props} />, }); console.log(html); // 这里可以把html传给父组件或者直接用于提交 }; return ( <> <DndProvider backend={HTML5Backend}> <CommentsProvider users={{}} myUserId="1"> <Plate plugins={plugins} initialValue={initialValue} editor={editor} onChange={() => { console.log("编辑器内容更新:", editor.children); }} > <FixedToolbar> <FixedToolbarButtons /> </FixedToolbar> <Editor /> <FloatingToolbar> <FloatingToolbarButtons /> </FloatingToolbar> <MentionCombobox items={[]} /> <CommentsPopover /> </Plate> </CommentsProvider> </DndProvider> <button onClick={handleGetHtml}>获取HTML</button> </> ); }; export default RichTextEditor;
集成React-Hook-Form的版本
如果要把编辑器集成到React-Hook-Form中,需要使用Controller组件来管理表单值,将编辑器内容转为HTML后同步到表单:
"use client"; import { plugins } from "@/lib/plugins"; import { CommentsProvider } from "@udecode/plate-comments"; import { Plate, createPlateEditor } from "@udecode/plate-common"; import { serializeHtml } from "@udecode/plate-serializer-html"; import { FC } from "react"; import { DndProvider } from "react-dnd"; import { HTML5Backend } from "react-dnd-html5-backend"; import { Controller, useForm } from "react-hook-form"; import { CommentsPopover } from "@/components/plate-ui/comments-popover"; import { Editor } from "@/components/plate-ui/editor"; import { FixedToolbar } from "@/components/plate-ui/fixed-toolbar"; import { FixedToolbarButtons } from "@/components/plate-ui/fixed-toolbar-buttons"; import { FloatingToolbar } from "@/components/plate-ui/floating-toolbar"; import { FloatingToolbarButtons } from "@/components/plate-ui/floating-toolbar-buttons"; import { MentionCombobox } from "@/components/plate-ui/mention-combobox"; interface FormValues { content: string; } const RichTextEditorForm: FC = () => { const { control, handleSubmit } = useForm<FormValues>(); const onSubmit = (data: FormValues) => { // 这里可以将data.content(HTML字符串)提交到数据库 console.log("提交的HTML内容:", data.content); // 调用API存库逻辑 }; return ( <form onSubmit={handleSubmit(onSubmit)}> <Controller name="content" control={control} defaultValue="" render={({ field: { onChange } }) => { const editor = createPlateEditor({ plugins }); // 编辑器内容变化时,同步生成HTML并更新表单值 const handleEditorChange = () => { const html = serializeHtml(editor, { nodes: editor.children, dndWrapper: (props) => <DndProvider backend={HTML5Backend} {...props} />, }); onChange(html); }; return ( <DndProvider backend={HTML5Backend}> <CommentsProvider users={{}} myUserId="1"> <Plate plugins={plugins} initialValue={[]} // 可根据defaultValue反序列化,需补充deserializeHtml逻辑 editor={editor} onChange={handleEditorChange} > <FixedToolbar> <FixedToolbarButtons /> </FixedToolbar> <Editor /> <FloatingToolbar> <FloatingToolbarButtons /> </FloatingToolbar> <MentionCombobox items={[]} /> <CommentsPopover /> </Plate> </CommentsProvider> </DndProvider> ); }} /> <button type="submit">提交表单</button> </form> ); }; export default RichTextEditorForm;
补充说明
- 如果需要从HTML反序列化到编辑器初始值,可以使用
deserializeHtml方法,对应serializeHtml的反向操作。 - 确保你的
plugins配置包含了所有需要序列化的节点插件,否则部分格式可能无法被正确转为HTML。
内容的提问来源于stack exchange,提问作者Eskalifer
相关产品推荐
相关产品推荐

