• 前端 富文本编辑器原理——从javascript、html、css开始入门



    yma16-logo

    ⭐前言

    大家好,我是yma16,本文分享关于前端 富文本编辑器原理——从javascript、html、css开始。
    富文本编辑器
    富文本编辑器是指具有格式化文本和图像编辑功能的文本编辑器

    参考文档:https://w3c.github.io/selection-api/#abstract

    ⭐html的contenteditable属性

    全局属性 contenteditable 是一个枚举属性,表示元素是否可被用户编辑。如果可以,浏览器会修改元素的组件以允许编辑。

    • contenteditable boolean (false | true) 默认false
      简单理解,加上contenteditable ,html可以编辑具有input 输入的基本功能,所见即所得。
      例:
      html demo 标签配置contenteditable
    DOCTYPE html>
    <html>
    	<head>
    		<meta charset="utf-8">
    		<title>富文本编辑器title>
    	head>
    	<style>
    		blockquote {
    		  background: #eee;
    		  border-radius: 5px;
    		  margin: 16px 0;
    		}
    		
    		blockquote p {
    		  padding: 15px;
    		}
    		
    		cite {
    		  margin: 16px 32px;
    		  font-weight: bold;
    		}
    		
    		blockquote p::before {
    		  content: '\201C';
    		}
    		
    		blockquote p::after {
    		  content: '\201D';
    		}
    		
    		[contenteditable='true'] {
    		  caret-color: red;
    		}
    
    	style>
    	<body>
    		<blockquote contenteditable="true">
    		  <p>Edit this content to add your own quotep>
    		blockquote>
    		
    		<cite contenteditable="true">-- Write your own name herecite>
    
    	body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    效果如下,可以输入编辑html元素:
    rich-text

    💖 输入的光标位置(浏览器获取selection)

    getSelection() method
    GetSelection ()方法返回一个 Selection 对象,该对象表示用户选择的文本范围或插入符号的当前位置。

    ⭐使用Selection.toString () 返回指定的文本

    例:

    <body>
    	<blockquote contenteditable="true">
    	  <p>Edit this content to add your own quotep>
    	blockquote>
    	
    	<cite contenteditable="true">-- Write your own name herecite>
    	<button onclick="printSelection()">console.log(getSelection)button>
    
    body>
    <script type="text/javascript">
    	const printSelection=()=>{
    		const selection=window.getSelection()
    		console.log('selection',selection)
    		console.log('selection.toString()',selection.toString())
    	}
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    效果如下:
    selection.toString

    ⭐getRangeAt 获取指定索引范围

    函数接受一个索引值
    返回,其中
    结束的索引值,endOffset
    开始的索引值,startOffset
    效果如下图:
    getRangeAt

    💖 修改光标位置

    调用 setStart() 和 setEnd() 方法,来修改一个光标的位置或拖蓝范围
    Range.setStart()
    Range.setStart() 方法用于设置 Range的开始位置。

    如果起始节点类型是 Text、Comment 或 CDATASection之一,那么 startOffset 指的是从起始节点算起字符的偏移量。对于其他 Node 类型节点,startOffset 是指从起始结点开始算起子节点的偏移量。

    如果设置的起始位点在结束点之下(在文档中的位置),将会导致选区折叠,起始点和结束点都会被设置为指定的起始位置。
    startNode
    startNode 用于设定 Range的起始位置。

    startOffset
    必须为不小于 0 的整数。表示从startNode的开始位置算起的偏移量。
    Range.setEnd()
    Range.setEnd()
    方法用于设置 Range的结束位置。

    如果结束节点类型是 Text、Comment 或 CDATASection之一,那么 endOffset 指的是从结束节点算起字符的偏移量。对于其他 Node 类型节点,endOffset 是指从结束结点开始算起子节点的偏移量。

    如果设置的结束点在起始点之上(在文档中的位置),将会导致选区折叠,起始点和结束点都会被设置为指定的结束位置。
    endNode
    endNode用于设定 Range的结束位置。

    endOffset
    必须为不小于 0 的整数。表示从endNode的结束位置算起的偏移量。
    语法

    range.setStart(startNode, startOffset);
    range.setEnd(endNode, endOffset);
    
    • 1
    • 2

    例:
    点击不失去焦点跳转开始和结束,避免失去焦点使用preventDefault

    <body>
    	<blockquote contenteditable="true">
    		<p>Edit this content to add your own quotep>
    	blockquote>
    
    	<cite contenteditable="true">-- Write your own name herecite>
    	<button onclick="printSelection()">console.log(getSelection)button>
    	<button id='start-id'>jumpt startbutton>
    	<button id='end-id'>jumpt endbutton>
    
    
    body>
    <script type="text/javascript">
    	function printSelection() {
    		const selection = window.getSelection()
    		console.log('selection', selection)
    		console.log('selection.toString()', selection.toString())
    		console.log('selection.getRangeAt(0)', selection.getRangeAt(0))
    	}
    
    	function jumpStart() {
    		let range = window.getSelection().getRangeAt(0);
    		let textEle = range.commonAncestorContainer;
    		range.setStart(range.startContainer, 0);
    		range.setEnd(range.startContainer, 0);
    	}
    
    	function jumpEnd() {
    		let range = window.getSelection().getRangeAt(0);
    		let textEle = range.commonAncestorContainer;
    		range.setStart(range.startContainer, textEle.length);
    		range.setEnd(range.endContainer, textEle.length);
    	}
    	window.onload = function() {
    		document.getElementById('start-id').addEventListener('click', function(e) {
    			jumpStart()
    		})
    		document.getElementById('start-id').addEventListener('mousedown', function(e) {
    			e.preventDefault()
    		})
    		
    		document.getElementById('end-id').addEventListener('click', function(e) {
    			jumpEnd()
    		})
    		document.getElementById('end-id').addEventListener('mousedown', function(e) {
    			e.preventDefault()
    		})
    	}
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    效果如下图:
    riche-editor-positon

    💖 设置选取range

    Selection.addRange()
    概述
    向选区(Selection)中添加一个区域(Range)。

    语法

    sel.addRange(range)
    
    • 1

    例子:
    失去焦点之后恢复选区

    <body>
    	<blockquote contenteditable="true">
    		<p>Edit this content to add your own quotep>
    		<b>yma16b>
    	blockquote>
    
    	<cite contenteditable="true">-- Write your own name herecite>
    	<br>
    	<button id='print-id'>console.log(getSelection)button>
    	<br>
    	<br>
    	<button id='start-id'>jump startbutton>
    	<button id='end-id'>jump endbutton>
    	<button id='focus-id'>focus contentbutton>
    
    
    body>
    <script type="text/javascript">
    	const config = {
    		selection: null
    	}
    
    	function printSelection() {
    		const selection = window.getSelection()
    
    		range = document.getSelection().getRangeAt(0).cloneRange();
    		config.cloneRange = range;
    		console.log('selection', selection)
    		// console.log('selection.toString()', selection.toString())
    		// console.log('selection.getRangeAt(0)', selection.getRangeAt(0))
    	}
    
    	function jumpStart() {
    		let range = window.getSelection().getRangeAt(0);
    		let textEle = range.commonAncestorContainer;
    		range.setStart(range.startContainer, 0);
    		range.setEnd(range.startContainer, 0);
    		range = document.getSelection().getRangeAt(0).cloneRange();
    		config.cloneRange = range;
    	}
    
    	function jumpEnd() {
    		let range = window.getSelection().getRangeAt(0);
    		let textEle = range.commonAncestorContainer;
    		range.setStart(range.startContainer, textEle.length);
    		range.setEnd(range.endContainer, textEle.length);
    		range = document.getSelection().getRangeAt(textEle.length).cloneRange();
    		config.cloneRange = range;
    	}
    
    	function focusContent() {
    		document.getSelection().removeAllRanges(); //把没用的Ranges删除
    		console.log('config.cloneRange',config.cloneRange)
    		document.getSelection().addRange(config.cloneRange); //恢复Range
    	}
    	window.onload = function() {
    		document.getElementById('print-id').addEventListener('click', function(e) {
    			printSelection()
    		})
    		document.getElementById('print-id').addEventListener('mousedown', function(e) {
    			e.preventDefault()
    		})
    		document.getElementById('start-id').addEventListener('click', function(e) {
    			jumpStart()
    		})
    		document.getElementById('start-id').addEventListener('mousedown', function(e) {
    			e.preventDefault()
    		})
    
    		document.getElementById('end-id').addEventListener('click', function(e) {
    			jumpEnd()
    		})
    		document.getElementById('end-id').addEventListener('mousedown', function(e) {
    			e.preventDefault()
    		})
    		document.getElementById('focus-id').addEventListener('click', function(e) {
    			focusContent()
    		})
    		document.getElementById('focus-id').addEventListener('mousedown', function(e) {
    			e.preventDefault()
    		})
    	}
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

    效果如下:
    focus-content

    ⭐总结

    Contenteditable属性
    Contenteditable是一种HTML属性,用于指定页面中的元素是否可以编辑。以下是Contenteditable的总结:

    1. Contenteditable属性可以应用于HTML元素上,如div、span、p、h1等等。

    2. 当Contenteditable属性设置为true时,用户可以编辑元素内的文本、图像等内容。

    3. Contenteditable属性的取值包括true和false,分别表示可编辑和不可编辑。

    4. Contenteditable属性可以通过JavaScript来动态修改。

    5. Contenteditable属性的兼容性很好,支持大多数现代浏览器。

    6. 虽然Contenteditable属性很方便,但也存在一些潜在的安全问题,因此应该谨慎使用。

    富文本编辑器

    富文本编辑器是一种允许用户编辑带有样式和格式的文本的编辑器。它与普通文本编辑器的区别在于,它允许用户使用各种字体、颜色、大小、加粗、斜体、下划线、超链接、图片等来设计和呈现文本内容。其原理主要包括以下几个方面:

    • DOM操作:富文本编辑器通过操作DOM树来实现文本样式和格式的改变。当用户在编辑器中输入或选择文本时,编辑器会将文本转换为DOM节点,并将节点添加到DOM树中。通过对DOM节点的增删改查,实现对文本样式和格式的修改操作。

    • 事件监听:通常情况下,富文本编辑器会监听用户的输入事件、鼠标点击事件和键盘事件等,以便及时捕捉用户的操作并做出相应的反应。

    • 样式和格式化:富文本编辑器通常内置了样式和格式化工具,比如字体、颜色、大小、加粗、斜体、下划线、超链接等,可以通过这些工具来控制文本的样式和格式。

    • 插件和组件:富文本编辑器可以通过插件和组件来扩展其功能,比如图片上传组件、表格插件、代码高亮插件等,可以让编辑器满足更多的需求。

    ⭐结束

    本文分享到这结束,如有错误或者不足之处欢迎指出!
    scene

    👍 点赞,是我创作的动力!
    ⭐️ 收藏,是我努力的方向!
    ✏️ 评论,是我进步的财富!
    💖 感谢你的阅读!

  • 相关阅读:
    Web前端:2022年最新web开发技术
    TensorFlow 的基本概念和使用场景
    229. 多数元素 II
    实现优雅的数据返回 - springboot
    docker学习记录(二)
    第16篇ESP32 platformio_arduino框架 wifi联网_连接WiFi热点并连接tcp server收发数据进行通讯
    # [AI]多模态聚类能力助力AI完成自主意识测试
    笔记软件 Keep It mac v2.3.3中文版新增功能
    C语言加密字符(ZZULIOJ1064:加密字符)
    如何用Jmeter提取和引用Token
  • 原文地址:https://blog.csdn.net/qq_38870145/article/details/133579239