实现一个简单的富文本编辑器

2,141 阅读3分钟

webpack 加 typescript 构建项目,基于 document.execCommand实现一个简单的富文本编辑器,只包含颜色、设置标题、粗体三个功能。document.execCommand api 详见 mdn 文档 document.execCommand。项目地址 miniEdit

contenteditable=true 和 document.execCommand

通过执行 document.execCommand,可以对标签的 contenteditable 属性为 true 的可编辑区域选中的文本进行设置,从而实现富文本编辑器的功能。而document.execCommand 提供了很多操作文本的命令,如设置文本的颜色,文本的大小,缩进等等。

安装相关依赖

安装主要依赖。 webpack、webpack-cli、ts-loader、typescript。下面是所有需要的包。

主要文件目录

lib 下的文件是富文本编辑器的实现的代码,包括样式和核心代码。 src 下的文件主要是为了开发时,配合 index.html 实例化一个编辑器。

lib-- (编辑器代码)

--index.js (生产时打包输出入口文件)

--main.ts (编辑器核心代码)

--index.css (编辑器样式)

src-- (import编辑器构造函数,并实例化,用于开发)

--index.css (html的样式)

--index.js (开发时打包的入口文件)

index.html (开发环境下,生成编辑器)

webpack 配置

这里分为两个配置文件。webpack.config.js 用来开发环境使用。入口文件在 src 目录下的 index.js 文件。

webpack.build.config.js 用来开发环境使用。入口文件在 lib 目录下的 index.js 文件。

功能的实现

因为通过 document.execCommand 可以对标签 contenteditable=true 的区域的选区产生影响。所以点击对应的按钮时执行相应的命令就可以对选中文字进行编辑。 'bold' 命令会将选取加粗'forecolor' 会将选区的文字设置成指定的颜色'fontSize' 可以将选区的文字设置成指定的大小

一个小坑

当可编辑区域选中了一些文字之后,再点击按钮执行 document.execCommand 会发现没有效果。原因是点击按钮时,可编辑区域失去焦点,造成选区丢失,执行命令失败。我们给按钮的点击事件做下处理就行了。 给按钮添加一个 onmousedown 事件处理程序,在事件处理程序中 event.preventDefault() 取消事件的默认行为。 之所以不在click事件中加是因为,onmousedown 事件会先于 click事件触发,所以onmousedown 事件触发时已经导致可编辑区域失去焦点。

处理上面的小坑的更好的方法

上面的方法缺点在于,我们只给按钮添加了 event.preventDefault(),那么点击其他区域,还是会失去选区,总不能页面所有元素都添加event.preventDefault()

Selection 对象表示用户选择的文本范围或插入符号的当前位置。那么我们可以将当前的选区缓存起来,在执行document.execCommand前,我们先利用缓存恢复之前的选区,再执行命令

// 在可编辑区域的onmouseleave事件处理程序中缓存选区
let selObj = window.getSelection();
// 鼠标leave时,缓存当前的选区,isCollapsed为false表示有选取,false表示的知识当前的焦点在可编辑区域
if (!selObj.isCollapsed) {
    cachedRange  = selObj.getRangeAt(0);
}

// 执行命令
var selObj = window.getSelection();
// 先清除掉选区
selObj.removeAllRanges()
// 再使用缓存的range
selObj.addRange(cachedRange)