如何通过react-quill处理器直接插入HTML(如<hr>标签)?
在React-Quill中插入
分割线的解决方案
分割线的解决方案
方法一:自定义Blot(推荐,符合Quill架构)
Quill基于Blot树结构工作,自定义Blot能让分割线更好地融入编辑器的编辑逻辑(比如删除、复制粘贴)。
- 注册自定义分割线Blot
导入Quill的Block Blot并创建自定义子类,注册到Quill中:
import ReactQuill, { Quill } from 'react-quill' import 'react-quill/dist/quill.snow.css' // 注册自定义分割线Blot const Block = Quill.import('blots/block') class HrBlot extends Block {} HrBlot.blotName = 'hr' HrBlot.tagName = 'HR' Quill.register(HrBlot)
- 实现插入逻辑
修改insertLine函数,利用Quill的insertEmbed方法插入分割线,并调整光标位置:
function insertLine(quill) { const range = quill.getSelection() if (range) { // 在当前光标位置插入分割线 quill.insertEmbed(range.index, 'hr', true) // 将光标移至分割线后方,方便继续编辑 quill.setSelection(range.index + 1) } }
- 添加样式确保显示正常
在组件所在的CSS文件或style标签中添加:
.ql-editor hr { border: none; border-top: 1px solid #ccc; margin: 1em 0; }
方法二:直接插入HTML(快速实现)
如果不想自定义Blot,可以借助Quill的剪贴板模块将HTML转换为Delta后插入:
function insertLine(quill) { const range = quill.getSelection() if (range) { // 将HTML转换为Quill可处理的Delta格式 const delta = quill.clipboard.convert({ html: '<hr>' }) // 插入内容到编辑器 quill.updateContents(delta, 'user') // 调整光标位置 quill.setSelection(range.index + 1) } }
完整修改后的组件代码
import ReactQuill, { Quill } from 'react-quill' import 'react-quill/dist/quill.snow.css' // 注册自定义分割线Blot(方法一使用,方法二可删除这段) const Block = Quill.import('blots/block') class HrBlot extends Block {} HrBlot.blotName = 'hr' HrBlot.tagName = 'HR' Quill.register(HrBlot) function insertLine(quill) { // 方法一实现 const range = quill.getSelection() if (range) { quill.insertEmbed(range.index, 'hr', true) quill.setSelection(range.index + 1) } // 方法二实现(替换上面的代码即可) // const range = quill.getSelection() // if (range) { // const delta = quill.clipboard.convert({ html: '<hr>' }) // quill.updateContents(delta, 'user') // quill.setSelection(range.index + 1) // } } const icons = Quill.import('ui/icons') icons['code-block'] = '<svg strokeWidth="0" viewBox="0 0 16 16" height="15" width="15" xmlns="http://www.w3.org/2000/svg"><path d="M9.293 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V4.707A1 1 0 0 0 13.707 4L10 .293A1 1 0 0 0 9.293 0zM9.5 3.5v-2l3 3h-2a1 1 0 0 1-1-1zM6.646 7.646a.5.5 0 1 1 .708.708L5.707 10l1.647 1.646a.5.5 0 0 1-.708.708l-2-2a.5.5 0 0 1 0-.708l2-2zm2.708 0 2 2a.5.5 0 0 1 0 .708l-2 2a.5.5 0 0 1-.708-.708L10.293 10 8.646 8.354a.5.5 0 1 1 .708-.708z"></path></svg>' const modules = { toolbar: { container: '#toolbar', handlers: { insertLine: insertLine } }, clipboard: { matchVisual: false, } } export default function TextEditor({ body, setBody }) { return ( <div> <style> {` .ql-editor hr { border: none; border-top: 1px solid #ccc; margin: 1em 0; } `} </style> <div id='toolbar' style={{borderBottomWidth: '0'}}> <span className='ql-formats'> <select className='ql-header' defaultValue='7' onChange={e => e.persist()}> <option value='1' /> <option value='2' /> <option value='7' /> </select> </span> <span className='ql-formats'> <button className='ql-bold' /> <button className='ql-italic' /> <button className='ql-underline' /> <button className='ql-strike' /> </span> <span className='ql-formats'> <button className='ql-blockquote' /> <button className='ql-link' /> <button className='ql-image' /> <button className='ql-code' /> <button className='ql-code-block' /> </span> <span className='ql-formats'> <button className='ql-list' value='ordered' /> <button className='ql-list' value='bullet' /> <button className='ql-insertLine' style={{transform: 'rotate(90deg)'}}> <svg stroke="currentColor" strokeWidth="0" viewBox="0 0 24 24" height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path fill="none" d="M0 0h24v24H0z"></path><path d="M4 22H2V2h2v20zM22 2h-2v20h2V2zm-8.5 5h-3v10h3V7z"></path></svg> </button> </span> </div> <ReactQuill theme='snow' value={body} onChange={setBody} modules={modules} /> </div> ) }
内容的提问来源于stack exchange,提问作者Moataz Ghazy
相关产品推荐
相关产品推荐

