50 行代码 React Hooks 中使用富文本编辑器
前言
继 50 行代码 Vue3 中使用富文本编辑器 之后,继续使用 wangEditor V5 实现 React 富文本编辑器。wangEditor V5 官方提供 React 组件,使用非常简单。
wangEditor V5 正在公开测试中,有问题和建议可以提交到 github issue 。
【注意】编辑器后续可能继续升级,API 和配置或许会调整。所以问题请及时查阅文档,不要仅依赖本文。
安装
使用 create-react-app 创建一个 React 开发环境,然后安装 wangEditor 必要的包
yarn add @wangeditor/editor yarn add @wangeditor/editor-for-react 复制代码
创建编辑器
写代码
创建 React 组件 MyEditor.js
,代码如下,大约 50 行,逻辑也非常简单。(源码在文章最后)
import React, { useState, useEffect } from 'react' import '@wangeditor/editor/dist/css/style.css' import { Editor, Toolbar } from '@wangeditor/editor-for-react' export default function MyEditor() { const [editor, setEditor] = useState(null) // 存储 editor 实例 const defaultContent = [] // 编辑器默认内容,空内容 const toolbarConfig = {} // 菜单栏配置 // 编辑器配置 const editorConfig = { placeholder: '请输入内容...', onCreated: (editor) => { // 编辑器创建之后,记录 editor 实例,重要 !!! (有了 editor 实例,就可以执行 editor API) setEditor(editor) }, onChange: (editor) => { // editor 选区或者内容变化时,获取当前最新的的 content console.log('changed', editor.children) } } // 组件销毁时,及时销毁 editor 实例,重要!!! useEffect(() => { return () => { if (editor == null) return editor.destroy() setEditor(null) } }, [editor]) return ( <div style={{ border: '1px solid #ccc', zIndex: 100}}> {/* 渲染 toolbar */} <Toolbar editor={editor} defaultConfig={toolbarConfig} style={{ borderBottom: '1px solid #ccc' }} /> {/* 渲染 editor */} <Editor defaultConfig={editorConfig} defaultContent={defaultContent} style={{ height: '500px' }} /> </div> ) } 复制代码
运行
把这个组件引入到 App.js
中,即可生成一个功能齐全的富文本编辑器。当编辑器内容发生变化时,会触发 onChange
打印编辑器最新内容。
注意事项
传入编辑器的默认内容
defaultContent
必须是 JSON 格式(不能是 html),数据结构参考这里onCeated
时记录editor
实例,方便后续执行 API组件销毁时,及时销毁
editor
防止内存泄漏
ajax 异步获取内容,再创建编辑器
定义一个 state isAjaxDone
来表示 ajax 是否请求完成,然后根据 isAjaxDone
的值来判断是否渲染编辑器。
// const defaultContent = [] const [defaultContent, setDefaultContent] = useState([]) const [isAjaxDone, setIsAjaxDone] = useState(false) // 模拟 ajax 请求 setTimeout(() => { setDefaultContent([ { type: "paragraph", children: [{ text: "ajax 异步获取的内容" }], } ]) setIsAjaxDone(true) }, 1500) return ( <div style={{ border: '1px solid #ccc', zIndex: 100}}> {/* 待 ajax 请求结束,再渲染 toolbar */} {isAjaxDone && <Toolbar ... />} {/* 待 ajax 请求结束,再渲染 editor */} {isAjaxDone && <Editor ... />} </div> ) 复制代码
配置
编辑器配置
上文代码中只配置了 placeholder
onCreated
onChange
作为示例。它还支持 readOnly
autoFocus
maxLength
等配置,可参考文档。
const editorConfig = { placeholder: '请输入内容...', onCreated: editor => {}, onChange: editor => {}, // 继续其他配置 } 复制代码
工具栏配置
如果你想修改工具栏的菜单,如隐藏某些菜单,重新排序分组,就可以使用该配置。支持 toolbarKeys
和 excludeKeys
,可参考文档。
const toolbarConfig = { toolbarKeys: [ /* 显示哪些菜单,如何排序、分组 */ ], excludeKeys: [ /* 隐藏哪些菜单 */ ], } 复制代码
菜单配置
如果你想对某个菜单进行配置,例如配置颜色、字体、字号,配置上传图片的 API 地址等,可以使用菜单配置。具体参考文档。
const editorConfig = { // 编辑器配置,如 placeholder onChange ... // 所有的菜单配置,都要在 MENU_CONF 属性下 MENU_CONF: { // 配置字号 fontSize: [ ... ], // 配置上传图片 uploadImage: { ... }, // 继续其他菜单配置 } } 复制代码
API
wangEditor 提供了丰富的 API ,可以帮助你进行任何编辑器操作。可参考文档。
配置相关的 API
内容处理相关的 API
节点操作相关的 API
选区操作相关的 API
自定义事件的 API
我们在上述代码中,已经在 onCreated
时记录了 editor
实例,所以想使用 API ,直接在 editor
上执行即可。
function getEditorText() { if (editor == null) return // editor 在上述代码中已经定义 console.log(editor.getText()) // 使用 editor API } return <> <button onClick={getEditorText}>getText</button> <div style={{ border: '1px solid #ccc', zIndex: 100}}> <Toolbar ... /> <Editor ... /> </div> </> 复制代码
获取内容,存储到服务器
编辑器的内容是 JSON 格式的,例如一段文字的数据格式为:
[{"type":"paragraph","children":[{"text":"文字内容"}]}] 复制代码
通过 editor.children
即可获取内容,ajax 提交到服务器。当然,也可以使用 onChange
把内容同步到 <textarea>
然后用 form 提交。
你可以使用
editor.getHtml()
获取 html 内容。
但请注意,如果仅保存 html 内容,将无法再次编辑。因为编辑器初始化时,仅能传入 JSON 格式的内容,不能传入 html 。
显示内容
从服务端获取编辑器的内容 content
,创建一个 editor
实例,即可获取 html 和纯文本,然后渲染页面。
import { createEditor } from '@wangeditor/editor' const editor = createEditor({ content }) editor.getHtml() editor.getText() 复制代码
PS:如果你想做服务端渲染 SSR ,这段代码也可以在 nodejs 中运行
总结
本文源码在这里。
wangEditor V5 正在公开测试中,有问题和建议可以提交到 github issue 。
作者:王福朋
链接:https://juejin.cn/post/7030584414652334093