Rich text editor for recording React

Main knowledge points: contentEditable and document.execCommand

Most of the input boxes used in daily use directly use input and support normal text operations, but if you want to do complex content input, you need a rich text editor, so I searched for information and started an exploration of rich text editors trip.

The first thing to use is the contentEditable attribute of the DOM element, which can change the DOM element to an editable state, that is, a cursor can appear after clicking, and a div node will be added every time the Enter key is clicked. Taking advantage of div's ability to contain everything, it is possible to develop a rich text editor through it.

Here comes the important point, div input can only input normal text, if you want to bold, italicize, insert pictures, hyperlinks, what should you do? This requires the use of document.execCommand , but this is an officially deprecated (no longer recommended) feature.

When an HTML document is switched to design mode, document exposes the execCommand method, which allows commands to be run to manipulate elements in the editable content area.

Most commands affect the selection of a document (bold, italic, etc.), while other commands insert new elements (add links) or affect entire lines (indent). When using contentEditable, calling execCommand() will affect the currently active editable element.

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

The commandNames that can be used by execCommand are as follows:

Order meaning example
backColor Modify the background color of the document. In styleWithCss mode, only the background color of the container element is affected. This requires a string value of type <color> to be passed as a parameter. Note that IE browsers use this to set the background color of text. document.execCommand(“backColor”, false, “#FF0000”)
bold Turn on or off the bold font effect of the selected text or insertion point. Internet Explorer uses <strong> tags instead of <b> tags.
copy Copy the current selection to the clipboard. The conditions for enabling this function vary from browser to browser, and the conditions for enabling it vary from time to time. Please check the browser compatibility table before use to determine availability.
createLink To create a hyperlink for the selected content, a hrefURI string is required to be passed in as the parameter value. URI must contain at least one character, such as a space. document.execCommand(“createLink”, false, “https://baidu.com”)
cut Cut the currently selected text and copy it to the clipboard. The conditions for enabling this function vary from browser to browser, and the conditions for enabling it vary from time to time. Please check the browser compatibility table before use to determine availability.
fontName Modify the font name at the insertion point or part of the selected text. A font name string (for example: "Arial") needs to be provided as an argument.
fontSize Modify the font size at the insertion point or part of the selected text. An HTML font size (1-7) needs to be provided as an argument.
foreColor Modify the font color at the insertion point or part of the selected text. A color value string needs to be provided as an argument.
heading Add a title tag at the cursor or on the selected text. Need to provide tag name string as parameter (eg: "H1", "H6") (not supported by IE and Safari) document.execCommand(“heading”, false, “H1”)
insertImage Inserts a picture at the insertion point (deletes the selected part). Requires a URL string as a parameter. The URL image address contains at least one character. Whitespace characters are also ok (IE will create a link with a value of null)
insertOrderedList Create an ordered list at the insertion point or selected text
insertUnorderedList Creates an unordered list at the insertion point or selected text.
italic Turn italics on or off at the cursor insertion point.
justifyCenter Center the text at the cursor insertion position or the selected content
justifyFull Aligns text at the cursor insertion position or selection.
justifyLeft Aligns the cursor position or selection to the left.
justifyRight Right-aligns the cursor insertion position or selection.
outdent Decreases the indentation of the line inserted by the cursor or the content of the selected line.
redo Redoes an undone operation.
undo Undoes the most recently executed command.
underline Turns the underline on or off at the cursor insertion point.
unlink Remove the <a> tag of the selected anchor link
formatBlock Adds an HTML block tag to the line containing the current selection, or replaces the containing block element if it already exists (in Firefox, BLOCKQUOTE is an exception - it will contain any containing block element). Requires a tag name char string as a parameter. Almost all block style tags can be used (eg. "H1", "P", "DL", "BLOCKQUOTE"). (IE browser only supports heading tags H1 - H6, ADDRESS, and PRE, and must be used when using Include tag separators < >, such as "<H1>".) document.execCommand(“formatBlock”, false, “H1”)
enableObjectResizing Enables or disables resizing handles for images and other objects. (IE browser does not support)
enableInlineTableEditing Enables or disables table row and column insertion and deletion controls. (IE browser does not support)
enableAbsolutePositionEditor Enables or disables grabbers that allow absolutely positioned elements to be moved. Firefox 63 Beta/Dev Edition disables this feature by default

formatBlock is a custom command that can create a label and wrap the selected content by entering the specified label name. For example: document.execCommand("formatBlock", false, "H1"), you can create an H1 tag, which has the same effect as 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标签,就会导致选中区域是空的,从而导致不生效。

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

Guess you like

Origin blog.csdn.net/qq_28992047/article/details/127298426