ReactJS实现Google Docs克隆:单工具栏控制多编辑器方案咨询
单工具栏控制多Jodit编辑器及多页面编辑器推荐
一、Jodit-react实现单工具栏控制多编辑器方案
核心思路是隐藏所有编辑器自带的工具栏,单独实现一个全局工具栏,通过监听编辑器容器的鼠标移入事件切换当前激活的编辑器,让工具栏操作指向激活的实例。
实现步骤与代码修改
- 统一编辑器配置:所有编辑器禁用自带工具栏,共享基础配置
- 管理编辑器实例:用对象ref存储所有编辑器实例,避免单个ref的冗余
- 跟踪激活编辑器:维护状态记录当前激活的编辑器实例
- 实现全局工具栏:添加自定义工具栏,点击按钮时调用激活编辑器的对应API
修改后的代码示例:
import React, { useMemo, useRef, useState } from "react"; import "jodit"; import "jodit/build/jodit.min.css"; import JoditEditor from "jodit-react"; const Editor = () => { // 用对象存储所有编辑器实例,key为page.id const editorsRef = useRef({}); const [pages, setPages] = useState([ { id: 1, content: "" }, { id: 2, content: "" }, { id: 3, content: "" }, ]); // 记录当前激活的编辑器实例 const [activeEditor, setActiveEditor] = useState(null); // 统一所有编辑器的配置,禁用自带工具栏 const editorConfig = useMemo( () => ({ height: 500, toolbar: false, // 隐藏自带工具栏 readonly: false }), [] ); const handleContentChange = (content, pageId) => { setPages(prev => prev.map(page => page.id === pageId ? { ...page, content } : page )); }; // 编辑器挂载后保存实例到ref const handleEditorReady = (editor, pageId) => { editorsRef.current[pageId] = editor; // 默认激活第一个编辑器 if (pageId === 1) setActiveEditor(editor); }; // 鼠标移入编辑器容器时切换激活实例 const handleEditorHover = (pageId) => { setActiveEditor(editorsRef.current[pageId]); }; // 工具栏按钮点击事件,调用Jodit的命令 const handleToolbarAction = (command) => { if (!activeEditor) return; // 调用Jodit的execCommand执行格式操作 activeEditor.execCommand(command); }; return ( <> {/* 全局工具栏 */} <div style={{ padding: "10px", borderBottom: "1px solid #ccc", margin: "0 250px" }}> <button onClick={() => handleToolbarAction('bold')} style={{ marginRight: "8px" }}>粗体</button> <button onClick={() => handleToolbarAction('italic')} style={{ marginRight: "8px" }}>斜体</button> <button onClick={() => handleToolbarAction('underline')} style={{ marginRight: "8px" }}>下划线</button> <button onClick={() => handleToolbarAction('insertOrderedList')}>有序列表</button> </div> {/* 多编辑器容器 */} {pages.map((page) => ( <div key={page.id} style={{ border: activeEditor === editorsRef.current[page.id] ? "2px solid blue" : "2px solid red", margin: "20px 250px" }} onMouseEnter={() => handleEditorHover(page.id)} > <JoditEditor ref={editor => editor && handleEditorReady(editor, page.id)} value={page.content} config={editorConfig} tabIndex={page.id} // 给每个编辑器不同的tabIndex onChange={(newContent) => handleContentChange(newContent, page.id)} /> </div> ))} </> ); }; export default Editor;
关键说明
- 编辑器实例管理:通过
handleEditorReady将每个编辑器实例存入editorsRef,方便后续调用 - 激活切换:
onMouseEnter事件触发时更新activeEditor,同时通过边框颜色区分激活状态 - 工具栏操作:利用Jodit内置的
execCommand方法执行格式命令,支持大部分常用编辑操作
二、支持多页面/多文档的编辑器推荐
如果需要更贴近Google Docs的多页面体验,以下编辑器更适合:
- Slate.js:完全可定制的富文本编辑器框架,适合从零构建多页面文档系统。可自定义页面组件,共享工具栏逻辑,灵活控制每个页面的内容和状态。
- CKEditor 5:支持构建多文档界面(MDI),可通过官方插件或自定义实现多个编辑器实例共享工具栏,同时提供成熟的富文本编辑能力。
- TinyMCE:支持多编辑器实例管理,可通过API控制任意实例的编辑操作,自带丰富的工具栏组件,容易实现全局工具栏切换目标编辑器的逻辑。
- Quill.js:轻量级富文本编辑器,可通过自定义模块和状态管理实现多页面共享工具栏,适合需要简洁界面的场景。
内容的提问来源于stack exchange,提问作者Asish Kumar Sharma
相关产品推荐
相关产品推荐

