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)