
可爱的猫猫镇楼
Contenteditable 是 HTML 的一个超好用的全局属性,有了它,就好像给网页里的各种元素(如:div)都加上了神奇的 "编辑开关" 。只要把它的值设置为 true,对应的元素马上就摇身一变,成了能让用户随意编辑的区域。
它的核心原理其实也不难理解,简单来说,就是把用户输入的内容,按照 HTML 的规则,转化成对应的 HTML 结构。比如你输入一段带格式的文字,它会自动帮你生成 b 标签(加粗)、i 标签(斜体)来标记格式,真正实现了 "所见即所得" 。
基础实现
接下来,我将用 Contenteditable 搭建一个超简易的富文本编辑器,带加粗、斜体等这些基本格式设置的那种,代码量不大,新手也能轻松拿捏。
xml
<!DOCTYPE html>
<html>
<head>
<style>
.editor-container {
border: 1px solid #ddd;
border-radius: 4px;
padding: 10px;
min-height: 200px;
}
.toolbar {
margin-bottom: 10px;
display: flex;
align-items: center;
}
.toolbar button {
margin-right: 5px;
padding: 5px 10px;
background: #f5f5f5;
border: 1px solid #ddd;
border-radius: 3px;
cursor: pointer;
}
.toolbar button:hover {
background: #e9e9e9;
}
.toolbar select,input {
margin-right: 5px;
}
/* 编辑器内容样式 */
.editor-content {
white-space: pre-wrap;
outline: none;
}
</style>
</head>
<body>
<div class="toolbar">
<button onclick="toggleBold()">B</button>
<button onclick="toggleItalic()">I</button>
<button onclick="toggleUnderline()">U</button>
<!-- 样式设置 -->
<select id="fontSize" onchange="setFontSize(this.value)">
<option value="12">12px</option>
<option value="14">14px</option>
<option value="16" selected>16px</option>
<option value="18">18px</option>
</select>
<input type="color" id="textColor" onchange="setTextColor(this.value)">
<button onclick="insertLink()">链接</button>
<button onclick="insertImage()">图片</button>
<button onclick="undo()">撤销</button>
<button onclick="redo()">重做</button>
</div>
<div class="editor-container" contenteditable="true" id="editor"></div>
<script>
document.execCommand('fontSize', false, 4);
// 基础功能实现
function toggleBold() {
document.execCommand('bold', false, null);
}
function toggleItalic() {
document.execCommand('italic', false, null);
}
function toggleUnderline() {
document.execCommand('underline', false, null);
}
// 设置字体大小
function setFontSize(size) {
let fontSize = size == 12 ? 2 : (size == 14 ? 3 : (size == 16 ? 4 : 5))
document.execCommand('fontSize', false, fontSize);
}
// 设置文本颜色
function setTextColor(color) {
document.execCommand('foreColor', false, color);
}
function insertLink() {
const url = prompt('请输入链接地址:');
if (url) {
document.execCommand('createLink', false, url);
}
}
function insertImage() {
const imgUrl = prompt('请输入图片地址:');
if (imgUrl) {
document.execCommand('insertImage', false, imgUrl);
}
}
// 撤销/重做
function undo() {
document.execCommand('undo', false, null);
}
function redo() {
document.execCommand('redo', false, null);
}
// 内容获取与保存
function getContent() {
return document.getElementById('editor').innerHTML;
}
function saveContent() {
localStorage.setItem('editorContent', getContent());
alert('内容已保存到本地存储');
}
// 加载历史内容
window.addEventListener('load', () => {
const savedContent = localStorage.getItem('editorContent');
if (savedContent) {
document.getElementById('editor').innerHTML = savedContent;
}
});
</script>
</body>
</html>
代码主要分为 3 个部分,最上面通过 style 标签包裹的是 CSS 部分,主要控制编辑器整体的样式,中间是 HTML 部分,主要由一系列按钮以及最重要的「编辑器」的 div 盒子组成,最下面 script 标签中则是 HTML 中按钮相对应的 JS 逻辑。
这块有两个关键点,一个就是给作为「编辑器」的 div 设置 contenteditable = true,这样它就成了一个可编辑的区域;另一个关键点就是 document.execCommand 方法,通过它来实现编辑器的各个功能。

上图就是这个简易编辑器的页面样式,主要包含了:加粗、斜体、下划线、字号、颜色、链接、图片、撤销、恢复等功能。这样,一个简单的富文本编辑器就基本成型啦!是不是很方便!
实际开发痛点
虽然我实际的工作过程中并不做富文本编辑器这方面的工作,但这块的工作之复杂、繁琐也是早有耳闻。使用 Contenteditable 富文本编辑器在实际开发中,会遇到不少让人头疼的问题,如:光标和选区问题,有用过的小伙伴可能有切身体会,我们在操作的过程中,这个光标位置和选区范围经常不太听话,明明看着光标在文字中间,获取到的位置信息却不对;选中文本后执行操作,效果也不是我们预期的那样。这主要是因为不同浏览器 对光标和选区的处理有差异,再加上 Contenteditable 自身机制的复杂性,就容易出现各种问题。
要解决这个问题,我们可以尝试借助 Range 和 Selection 这两个 JavaScript 对象。Range 对象能精确表示文档中的一个区域,通过它可以获取和操作选区的起始位置、结束位置等信息 。Selection 对象则代表用户当前选中的区域,比如可以用它来判断是否有文本被选中,以及获取选中的文本内容。
优缺点
Contenteditable 的优点是非常明显的:
- 简单易用,开箱即用
- 轻量级,性能佳
- 原生支持键盘操作
- 实时生成 HTML代码
但是它的缺点不可忽视:
- 浏览器兼容性问题
- 复杂格式控制困难
- 粘贴富文本内容容易导致代码冗余
- 移动端兼容性
因此,如果只是实现简单的富文本编辑功能,Contenteditable 是个不错的选择,能满足很多基础场景的需求;但要是遇到复杂的功能要求,还是推荐使用像 TinyMCE、Quill 这样成熟的富文本编辑库 。不过,掌握 Contenteditable 的原理,能让我们在面对定制化需求时,有更灵活的应对思路。
以上,就是 Contenteditable 实现简单富文本编辑器相关的全部内容,如果对您有帮助,那是对我最好的激励!如果您感兴趣的话,点个关注吧!我会持续更新的!