近况
最近由于公司业务上的需求,我们需要一个自己的编辑器来编写我们得到APP里面的订阅文章,为什么需要自己的编辑器,主要是因为用第三方的编辑器很难完成公司定制化的需求,比如:排版上我们想要更好看点,统一,因为各个订阅专栏编辑的人不一样,容易造成各种不同的审美差异,解决方案有2种:
采用一个可定制化的第三方富文本编辑器,然后自己写插件来满足自己的要求。
自己写一个富文本编辑器。
最后和团队的人商量决定,自己撸一个吧,因为使用第一种方案,依赖于别人的开源插件,总是不太放心,而且害怕到时候有什么问题,要研究他们的源码,那就跟自己写差不多多少,而且我们自己撸一个,并非要写一个非常通用,可以开源的富文本编辑器,我们只需要针对我们自己业务,写一个定制化符合公司使用的编辑器就行了。综上,我开始了这次非常愉快(坑爹)的编辑器之旅!!!
先看效果图,如图所示,如果有订阅了我们得到APP里面专栏文章的,可以对比下,现在和8月的文章就能看出来了。
无处不在的坑
首先web端的富文本编辑器,基本命令参照documen命令文档,兼容性的问题就不说了,大家都知道,主要说说一些开发了才能知道的坑。
div还是p
可编辑模式下(是否支持可编辑可以用HTMLElement.isContentEditable
命令来查看的),如果内部没有P标签这个初始化标签,编写的时候,换行给你添加的标签将会是div,如图所示:
这里就已经不太符合我们要求了,不想要各种div标签在文本外面,语义化来说,我们应该用p标签才对。
解决方案: 初始化添加一个p标签,并且里面加入一个br
<p><br></p>
删除也要小心翼翼
这个坑跟第一个同样的原因,只是表现形式不同,如果你开始删除你的编辑文本,删除完之后,整个可编辑元素,就变成空了,意味着,又没有初始化的p标签,那么你在添加文字的时候,就会跟上面的问题一样了。
解决方案:监听删除动作,判断内部还是否有子元素,没有初始化p标签
行内标签很有个性
添加文本需要的行内标签,例如: bold,italic,underline,subscript等等,可以任意添加和取消,一般来说没有任何问题,需要注意的是,你不能随意更改相关标签的css特殊样式,炒个栗子:bold在chrome里面添加一个b标签,浏览器样式,font-weight:bolder;
,如果你自己css给覆盖掉,变成 font-weight: normal;
,那么再次点击,应该取消的时候,不会成功的。原因我没有找到文档,据我推测,因为是取消的时候,判断条件为是否有相关命令的css样式,并不是单纯的文字外部标签名称。
formatBlock跟你说,不是所有的牛奶都是特仑苏!
使用formatBlock来添加或者更换文字的外标签时,要特别注意--BLOCKQUOTE这个东东,
document.execCommand('formatBlock', false, "<blockquote>")
,它能添加或者更换,但是要取消他的时候,就不起作用了。
解决方案: 在执行代码的时候,多加一个判断,判断当前选中文字的外标签是什么,再决定是需要执行什么命令。
let Range = document.getSelection().getRangeAt(0),
formatName = Range.commonAncestorContainer.parentElement.nodeName === 'BLOCKQUOTE' ? 'P' : 'BLOCKQUOTE';
document.execCommand('formatBlock', false, formatName)
removeFormat并不是万能的
清楚格式这个命令,主要会清除掉附带在标签上的内联样式,也就是style,但是不会清除class名称,这意味着,从外部粘贴过来的文本,如果不幸的ClassName和你的css里面的ClassName重复了,就会带上你的css样式。而且也不会清楚里面内联元素标签,什么意思呢?就是span都还是存在的,从原理上来说这个不影响最后的显示,但没有必要需要这些个标签,很容易产生其他的问题。
解决方案:执行清楚格式操作的时候,多加一些操作,把无用的样式,标签和ClassName全部干掉。(此处必须有杀气!)
其他
至于其他的很多命令(indent,fontSize,fontColor...),我这里没有使用,也不知道是否有坑,原因是前面说到的样式统一,保证美观,不支持内联样式,由统一的css样式渲染。