记录React之富文本编辑器

主要知识点:contentEditable 以及 document.execCommand

日常使用的输入框,大多直接使用input,支持正常的文本操作,但是想要做复杂的内容输入,就需要一个富文本编辑器,所以我就查找资料,开始了一段富文本编辑器的探索之旅。

首先使用的是DOM元素的contentEditable属性,该属性可以将DOM元素改为可编辑状态,也就是点击后可以出现光标,每次点击回车键,都会重新添加一个div节点。利用div可包万物的特性,所以可以通过它来开发一款富文本编辑器。

重点来了,div输入也只能输入正常的文本,如果想加粗,斜体,插入图片,超链接,该怎么办?这就需要用到document.execCommand了,但是这是一个被官方弃用(不再推荐使用)的特性。

当一个 HTML 文档切换到设计模式时,document 暴露 execCommand方法,该方法允许运行命令来操纵可编辑内容区域的元素。

大多数命令影响document的 selection(粗体,斜体等),当其他命令插入新元素(添加链接)或影响整行(缩进)。当使用contentEditable时,调用 execCommand() 将影响当前活动的可编辑元素。

/**
* 语法:
* @param{string} aCommandName 命令的名称
* @param{boolean} aShowDefaultUI 是否展示用户界面
* @param{} aValueArgument 一些命令(例如 insertImage)需要额外的参数(insertImage 需要提供插入 image 的 url),默认为 null。
*/
var bool = document.execCommand(aCommandName, aShowDefaultUI, aValueArgument);
// 如果执行成功,则返回true,反之,返回false

execCommand可使用的commandName有以下几种:

命令含义示例
backColor修改文档的背景颜色。在 styleWithCss 模式下,则只影响容器元素的背景颜色。这需要一个<color> 类型的字符串值作为参数传入。注意,IE 浏览器用这个设置文字的背景颜色。document.execCommand(“backColor”, false, “#FF0000”)
bold开启或关闭选中文字或插入点的粗体字效果。IE 浏览器使用 <strong>标签,而不是<b>标签。
copy拷贝当前选中内容到剪贴板。启用这个功能的条件因浏览器不同而不同,而且不同时期,其启用条件也不尽相同。使用之前请检查浏览器兼容表,以确定是否可用。
createLink为选中内容创建超链接,需要一个hrefURI 字符串作为参数值传入。URI 必须包含至少一个字符,例如一个空格。document.execCommand(“createLink”, false, “https://baidu.com”)
cut剪贴当前选中的文字并复制到剪贴板。启用这个功能的条件因浏览器不同而不同,而且不同时期,其启用条件也不尽相同。使用之前请检查浏览器兼容表,以确定是否可用。
fontName在插入点或者选中文字部分修改字体名称。需要提供一个字体名称字符串 (例如:“Arial”) 作为参数。
fontSize在插入点或者选中文字部分修改字体大小。需要提供一个 HTML 字体尺寸 (1-7) 作为参数。
foreColor在插入点或者选中文字部分修改字体颜色。需要提供一个颜色值字符串作为参数。
heading添加一个标题标签在光标处或者所选文字上。需要提供标签名称字符串作为参数(例如:“H1”、“H6”)(IE 和 Safari 不支持)document.execCommand(“heading”, false, “H1”)
insertImage在插入点插入一张图片(删除选中的部分)。需要一个 URL 字符串作为参数。这个 URL 图片地址至少包含一个字符。空白字符也可以(IE 会创建一个链接其值为 null)
insertOrderedList在插入点或者选中文字上创建一个有序列表
insertUnorderedList在插入点或者选中文字上创建一个无序列表。
italic在光标插入点开启或关闭斜体字。
justifyCenter对光标插入位置或者所选内容进行文字居中
justifyFull对光标插入位置或者所选内容进行文本对齐。
justifyLeft对光标插入位置或者所选内容进行左对齐。
justifyRight对光标插入位置或者所选内容进行右对齐。
outdent对光标插入行或者所选行内容减少缩进量。
redo重做被撤销的操作。
undo撤销最近执行的命令。
underline在光标插入点开启或关闭下划线。
unlink去除所选的锚链接的<a>标签
formatBlock添加一个 HTML 块式标签在包含当前选择的行,如果已经存在了,更换包含该行的块元素 (在 Firefox 中,BLOCKQUOTE 是一个例外 -它将包含任何包含块元素). 需要提供一个标签名称字符串作为参数。几乎所有的块样式标签都可以使用 (例如。“H1”, “P”, “DL”, “BLOCKQUOTE”). (IE 浏览器仅仅支持标题标签 H1 - H6, ADDRESS,和 PRE,使用时还必须包含标签分隔符 < >, 例如 “<H1>”.)document.execCommand(“formatBlock”, false, “H1”)
enableObjectResizing启用或禁用图像和其他对象的大小可调整大小手柄。(IE 浏览器不支持)
enableInlineTableEditing启用或禁用表格行和列插入和删除控件。(IE 浏览器不支持)
enableAbsolutePositionEditor启用或禁用允许移动绝对定位元素的抓取器。Firefox 63 Beta/Dev Edition 默认禁用此功能

formatBlock是一个自定义的命令,可以通过输入指定的标签名,进行创建标签并包裹选中内容。例如这种:document.execCommand(“formatBlock”, false, “H1”),就可以创建一个H1标签,与 document.execCommand(“heading”, false, “H1”) 效果相同

效果图
这是我创建的富文本效果图,使用了react+antd

工具箱设置为:

const exec = (commandName, value = null) => {
  var a = document.execCommand(commandName, false, value);
  console.log(a, commandName, value);
};

const tools = [
      {
        key: 'bold',
        icon: <b>B</b>,
        title: '加粗',
      },
      {
        key: 'italic',
        icon: <i>I</i>,
        title: '斜体',
      },
      {
        key: 'underline',
        icon: <u>U</u>,
        title: '下划线',
      },
      {
        key: 'justifyLeft',
        icon: <AlignLeftOutlined />,
        title: '左对齐',
      },
      {
        key: 'justifyCenter',
        icon: <AlignCenterOutlined />,
        title: '居中对齐',
      },
      {
        key: 'justifyRight',
        icon: <AlignRightOutlined />,
        title: '右对齐',
      },
      {
        key: 'insertOrderedList',
        icon: <OrderedListOutlined />,
        title: '有序列表',
      },
      {
        key: 'insertUnorderedList',
        icon: <UnorderedListOutlined />,
        title: '无序列表',
      },
      {
        key: 'createLink',
        icon: <LinkOutlined />,
        title: '超链接',
        onClick() {
          setModalType('createLink');
        },
      },
      {
        key: 'formatBlock',
        icon: 'H',
        title: '标题',
        mode: 'hover',
        hoverDom: (
          <ul>
            {[1, 2, 3, 4, 5, 6].map((item) => (
              <li>
                {/* <a href="javascript:;" onClick={() => exec('formatBlock', 'H1')}> */}
                <Button onClick={() => exec('formatBlock', 'H1')}>
                  H{item}
                </Button>
                {/* </a> */}
              </li>
            ))}
          </ul>
        ),
      },
]

期间有个问题,创建标签工具时,怎么都无法给选中内容添加H1标签,但是单独给button使用document.execCommand(“heading”, false, “H1”)是可以的,说明了Button可以,div不可以。之后又尝试了一下a标签,如果不加href=“javascript:;”,也不能正常添加,加上后就可以正常添加了。
由此可见,document.execCommand命令不能在 普通文本的节点上使用(该节点不能被选中文本),否则点击文本时,浏览器会认为你开始了新的选择文本动作,导致之前的选中区域失效,此时再去添加H1标签,就会导致选中区域是空的,从而导致不生效。

有兴趣的可以自己尝试一下。感谢您的阅读,有问题可以留言,或者私信。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值