概述
这篇文章主要是来记录一下通过Webpack+TS实现的一个富文本编辑器。
主要功能如下:
- 实现一个编辑区域
- 实现"加粗", "设置标题", "设置颜色"三个简易功能
Webpack配置
既然决定要使用TS,那么就可以通过webpack搭配ts-loader或者awesome-typescript-loader来对ts语言进行编译。相应的webpack配置文件也非常好写,这里就简单贴张截图。
开发流程
接下来,我将自上而下来描述我是如何将这个富文本编辑器实现出来的。
设计思路
我认为首先应该从使用的角度入手,也就是说假设所有的功能都以及实现好了,通过这种假象的方式来决定我们的整个项目结构。 我这里的话是参考了wangeditor的使用方式:
const Editor = window.Editor;
const editor = new E('#container');
editor.create()
于是呢,我便依样画葫芦,我的简易编辑器使用方式如下:
const editorDom = document.getElementById("root");
const editor = new EasyEditor(editorDom);
editor.create();
window.editor = editor;
与wangeditor不同点就在于传入构造函数的参数不同,我要求传入的是一个dom节点,而wangeditor要求传入的是一个类似于jquery获取元素的参数值。
实现富文本编辑器关键问题
- 实现一个编辑区域
这个非常简单,只要留意过H5新Api的小伙伴应该都会注意到contenteditable属性. 只要将该属性设置为true。那么该DOM元素的区域就是一个可编辑区域。
- 实现"加粗", "设置标题", "设置颜色"三个简易功能
可以说,这三个功能其实都是对某部分字体加上样式,通过一番资料查阅,我发现浏览器提供给我们一个api: document.execCommand, 该api允许我们运行命令来操纵可编辑内容区域的元素。
下面做一个小演示:
首先我们在编辑区域选中一段字体:
然后我们在控制台执行document.execCommand("bold", false, null)
, 将选中部分字体加粗
函数执行返回true, 即浏览器支持该操作; 若返回false, 那就是不支持该操作。
除了加粗外,还有其它很多命令,如设置font-size,设置color等。在MDN上都有说明。
至此,我们逐个击破了两大主要问题,接下来就是通过代码来进行实现啦。
代码实现
虽然功能简单, 但代码还是不少的, 因此下面只贴出重要的代码。
初始化菜单栏以及编辑区
菜单项栏是通过一个menuItems
数组来动态渲染的,可以由用户提供,若用户没有提供,则使用系统自带的。
[
{
text: "H",
children: [
{ text: '一级标题', command: 'fontSize-6' },
{ text: '二级标题', command: 'fontSize-5' },
{ text: '三级标题', command: 'fontSize-4' },
{ text: '四级标题', command: 'fontSize-3' },
{ text: '五级标题', command: 'fontSize-2' },
{ text: '六级标题', command: 'fontSize-1' }
]
},
{
text: "B",
command: "bold"
},
{
text: "C",
children: [
{text: "red", command: "foreColor-red"},
{text: "blue", command: "foreColor-blue"},
{text: "green", command: "foreColor-green"},
]
}
]
文本编辑区中,默认换行使用的是div
,参照wangeditor的,使用document.execCommand("defaultParagraphSeparator", false, "p")
可以将默认换行标签改成p
标签
在渲染菜单项的时候,是允许有二级菜单的。同时,command会通过setAttribute绑定到生成的dom上。以便后续对编辑区域进行操作。
最后还有一个问题,那就是当选中了编辑区中部分内容后,点击菜单栏按钮会失去选中部分。这样document.execCommand
就失效了。
我的解决办法是: 每次鼠标抬起时都将当前选中的部分缓存起来,以便后续虽然失去选中部分,但仍然可以找回选中部分。经过一番资料查阅,我找到了window.getSelection
这个函数可以返回用户选择文本的一些信息,以下是MDN官方文档提供的示例:
function foo() {
let selection = window.getSelection();
let cacheRange = selObj.getRangeAt(0);
// 其他代码
}
拿到cacheRange
那这就好办了,这要把它存起来,等到点击菜单栏的时候,再把它放回selection
中,然后使用document.execCommand
执行命令即可。
function initEvent(dom: HTMLElement,editor: EasyEditor) {
// 绑定鼠标抬起缓存range事件
dom.addEventListener("mouseup", function(e) {
editor.cacheRange = window.getSelection().getRangeAt(0);
})
}
// 通过事件委托, 把每个菜单项的点击事件委托到菜单上
menuDom.addEventListener('click', function(e) {
const targetDom = e.target as HTMLElement;
const command = targetDom.getAttribute('command');
if(!command) return ;
if(editor.cacheRange) {
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(editor.cacheRange);
handleCommand(command); // 解析并执行绑定在dom上的命令
}
})
效果截图
总结
整个实现的过程为两天,有一天半的时间花在了调研查资料,工程规划上。写代码时间占比还是比较少的。
从0到1实现了一个富文本编辑器,可以说是很少有这种经历,以往都是在算法上掰扯,精心实现某一个模块,对写工程的经验比较少,还是得多多练习。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!