由于公司有个功能,需要用到用到富文本编辑器,最初便选择了简单便捷的wangEditor,可经过一年的使用情况来看,wangEditor已经逐渐无法满足用户各式各样的需求了,几经挑选最终决定换成TinyMCE,以下便是踩过一大堆坑后总结下来的一些经验~
安装TinyMCE
话不多说,直接npm install tinymce冲冲冲
npm install tinymce
TinyMCE默认是英文界面,想使用中文版的别忘了下载汉化包~
初始化
引入文件
import tinymce from 'tinymce'
加载tinymce
因为我是直接使用的tinymce而非tinymce-vue,所以html代码中应用textarea组件
html:
<textarea id="uTinymce"></textarea>
js:
tinymce.init({
selector: '#uTinymce',
height: 500
})
在init之后,会发现浏览器报Uncaught SyntaxError: Unexpected token '<'
的错,检查之后发现是因为theme.js没加载到,因此需要手动引入。后续仍然会有部分文件报这个错误,所以在下面一并引入了
import 'tinymce/themes/silver/theme'
import 'tinymce/icons/default'
引入相关文件后发现,虽然控制台没有报错,但是编辑器无法显示而是一片空白,经过检查之后发现,需要将tinymce中的skins文件夹放至本地引用,于是我就在项目的public文件夹下新建了tinmce文件夹,顺便将之前下载的汉化包也挪了过去
做完这一步后,需要在生成富文本之前,将样式资源的引用地址指向新建的文件夹,并且导入汉化包
window.tinymce.baseURL = `${window.location.origin}/js/tinymce`
tinymce.init({
selector: '#uTinymce',
height: 500,
language_url: 'js/tinymce/langs/zh_CN.js',
language: 'zh_CN',
})
于是乎~大功告成!
踩坑记录
虽然只是简简单单的生成了富文本编辑器,但是途中踩过的坑可真是不少。。做之前在网上搜索其他人是怎么做的,貌似都是集成了tinymce-vue,但是我做完之后发现tinymce-vue并没有起到作用,所以就给去掉了,以下是遇到的一些奇奇怪怪的问题
1、标签保存自定义属性后换行异常
由于业务的特殊性,我需要在富文本中插入一些带有自定义属性的输入框,类似于<input fieldname='xxx'>
这种代码,根据官方api,我直接选择了在init方法中配置valid_elements: '*[*]'
属性用于保存所有标签中的所有属性。
却没想到这个配置导致了换行之后,
标签被直接清除的问题
再到api中寻寻觅觅,发现了remove_trailing_brs: false
可以使末端节点的
标签保存,然而又双叒叕发现,保存富文本框中的代码时,
标签会自动转换为回车换行符
最后只能投机取巧,将tinymce.js的源码拉到本地,在里面找到了换行时插入
标签的方法emptyBlock
将其中的data-mce-bogus="1"
给删掉才得以解决(因为编辑器是根据这句代码将
标签题替换成换行符的)
2、多个路由打开编辑器,切换路由后编辑器加载异常及内容丢失
本来开开心心提测,却又被发现,当多个路由打开富文本编辑器,或者切换路由时,富文本编辑器会变得无法编辑且内容消失等异常问题,解决此问题需要经过以下几点操作:
首先,需要给每个富文本编辑器一个独立的id,我的解决方法是将富文本编辑器作为子组件引入,并通过时间戳生成唯一id传递保存
其次,需要在路由跳转时,将富文本编辑器销毁,并在重新进入页面时再次加载,具体流程可参考https://github.com/PanJiaChen/vue-element-admin
中的代码(感谢大佬),具体代码位置在:src-components-Tinymce-index.vue中可以看到
3、粘贴文本清除格式导致重复粘贴
由于业务特殊性,需要对富文本编辑器进行特殊处理,将粘贴进来的内容清除格式,但是给富文本编辑器绑定paste方法后,由于第2点中,对富文本进行重新加载的处理方式导致了刷新页面时,同时存在两个富文本编辑器的情况下,第二个进入的编辑器会绑定两次paste方法,从而导致粘贴进去的文本信息会被粘贴两次,我的解决办法是在第一次进来的时候给编辑器加上标识,若已有标识,便不需要再次绑定paste方法
let doc = document.querySelector(`#${_this.tinymceId}_ifr`).contentWindow.documentlet docTinymce = doc.querySelector('#tinymce')if (docTinymce.className.indexOf('pasteHasBind') === -1) { //由于activated方法,当多个路由打开了tinymce编辑器时,第二个进来的会加载两次,如果不加以判断,粘贴方法会重复绑定两次,导致粘贴数据异常 docTinymce.addEventListener('paste', function pasteDo(ev) { //清除被粘贴文本的格式 event.preventDefault() var text var clp = (event.originalEvent || event).clipboardData // 兼容针对于opera ie等浏览器 if (clp === undefined || clp === null) { text = window.clipboardData.getData('text') || '' if (text !== '') { if (window.getSelection) { // 针对于ie11 10 9 safari var newNode = document.createElement('span') newNode.innerHTML = text tinyMCE.editors[_this.tinymceId].insertContent(newNode) } else { // 兼容ie10 9 8 7 6 5 tinyMCE.editors[_this.tinymceId].insertContent(text) } } } else { // 兼容chorme或hotfire text = clp.getData('text/plain') || '' if (text !== '') { tinyMCE.editors[_this.tinymceId].insertContent(text) } } }) docTinymce.classList.add('pasteHasBind')}
结语
以上便是我在用到TinyMCE时遇到的问题,作为一个总结分享给大家,第一次写文章,可能许多地方表述的不是很清楚,可能有些地方写的还有些问题,希望大家多多指教!
版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 作者: 叽里呱啦的阿松 原文链接:https://juejin.im/post/6921986236408152077