You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过react-quill处理器直接插入HTML(如<hr>标签)?

在React-Quill中插入
分割线的解决方案

方法一:自定义Blot(推荐,符合Quill架构)

Quill基于Blot树结构工作,自定义Blot能让分割线更好地融入编辑器的编辑逻辑(比如删除、复制粘贴)。

  1. 注册自定义分割线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)
  1. 实现插入逻辑
    修改insertLine函数,利用Quill的insertEmbed方法插入分割线,并调整光标位置:
function insertLine(quill) {
  const range = quill.getSelection()
  if (range) {
    // 在当前光标位置插入分割线
    quill.insertEmbed(range.index, 'hr', true)
    // 将光标移至分割线后方,方便继续编辑
    quill.setSelection(range.index + 1)
  }
}
  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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 01:04:55