前后端分离项目中使用富文本编辑器UEditor

UEditor官网地址 http://fex.baidu.com/ueditor/

最近使用富文本编辑器Braft Editor、wangEditor多少都有一些问题。于是使用了比较老牌的富文本编辑器UEditor。虽然也有一些问题,但是好在踩过坑的人多,一般的问题都可以解决。这里总结一下。

1. UEditor实现onChange事件。

UEditor自身提供了contentChange事件,但是UEditor的contentChange事件有bug,按住Shift再输入内容,不会触发事件,比如很多标点符号或大写字母的输入就无法触发contentChange事件。 selectionChange事件也有同样的bug。

处理办法,监听UEditor初始化后的iframe中的body的input事件,在这个input事件中手动触发UEditor的contentChange事件。

var body = ueditor.body;
body.addEventListener('input', function() {
    ueditor.fireEvent('contentChange');
});

这样做存在问题: 对于没有按住Shift的输入会触发两次contentChange事件,自身封装的React的组件需要有个过滤,避免一些可能的性能问题。

为什么不直接使用input事件呢,因为富文本内容的有些变化并不是通过input事件引起的。比如插入图片,这些都由UEditor内部自己去触发contentChange事件。

2.UEditor中实现placeholder

当富文本中没有内容的时候给绝对定位显示一个div。
依然用到iframe中的body。给它绑定focus事件和blur事件。

body.addEventListener('focus', () => {
    //隐藏
});
                
body.addEventListener('blur', () => {
    //判断富文本中是否有内容,决定显示与隐藏placeholder
});

另外要注意如果手动修改了富文本中的值也要去判断一下placeholder的隐藏与显示,比如执行了ueditor.setContent。
点击到placehlder的div上手动触发body的focus,隐藏placeholder。

3.删除UEditor有序列表导出li标签带的p标签。

默认从UEditor中导出的有序列表无序列表是这样的结构:

导致使用富文本中内容的时候可能会有显示上的问题。在UEditor源码找到一个配置参数:
disablePInList: true, //导出有序列表的时候把p标签去掉
加上之后导出的就是

这样了。

4.去掉UEditor的自动保存。enableAutoSave:false

UEditor有一个自动保存的功能,默认会把编辑器中的内容保存到localStorage中。这个功能不需要的话配置enableAutoSave:false可以关闭。
但是要注意1.4的版本这样配置可能没有用。 需要到github上下载1.5的版本自己grunt编译一下使用。

5.百度UEditor编辑器关闭抓取远程图片功能 catchRemoteImageEnable: false

测试发现上传图片之后再执行一些粘贴操作的时候,原来上传的图片全部变成了loading状态,不能正常显示。这是因为对于不同域的图片,ueditor会尝试重新上传到本域,就会出现这样的情况。

6.输出过滤。

在图片上传中用户执行提交操作,这个时候取到的富文本内容会包含一个这样的loading图。 这显然是不合理的。
处理办法是在contentChange的时候往组件上层传递onChange(value)的时候对value进行过滤。
比如使用jq过滤。注意要尽量减少过滤操作。在组件中缓存过滤前的值,如果值没变,就不去执行过滤,不往上触发onChange事件。

var html = ueditor.getContent();
var filterdHtml =
    $(`
${html}
`) .find('.loadingclass') .remove() .end() .prop('innerHTML') || '';

该功能可通过修改上传图片的插件实现,见第8条。

7.UEditor前后端解耦。

UEditor有部分配置会在后端,比如图片上传的部分配置,UEditor会调接口去请求。 这不符合我们的项目情况:一来服务端不一定方便给你返回这个配置也没有比要,二来用UEditor中的方法来加载这个配置文件还很容易遇到跨域的问题。
修改源码:
1.将原来服务端返回过来的配置放到 ueditor.config.js中。 比如图片上传的配置。
2.修改源码ueditor.all.js中loadServerConfig方法。 注释掉setTimeout方法中try …catch请求服务端内容相关的内容,需要以下两句以保持编辑器的其他逻辑正常。
me.fireEvent(‘serverConfigLoaded’);
me._serverConfigLoaded = true;

8.UEditor使用自定义接口图片上传。

一般公司都有固定的中台上传接口和返回格式,跟ueditor的不一样。所以用ueditor上传有2个方案。一个是新写一个上传组件显示在工具栏,二个是修改自带的上传组件simpleupload。这里采用第二种,修改插件。
这个插件使用了iframe来上传,实际应用中也会出现跨域的问题。所以我们修改它的上传方法。拿到file后 根据配置文件的的格式和内容来判断文件是否符合要求,然后使用

var xhr = new XMLHttpRequest();
var fd = new FormData();

来上传并执行回调。

上传成功或失败需要设置 input.value="" 避免再次上传同一个文件时点击按钮无反应。

输出过滤:getContent的时候过滤掉上传中和上传失败的图片,在该插件的outputRule中添加 loadingclass的过滤。

if (/\b(loaderrorclass)|(bloaderrorclass)\b/.test(n.getAttr('class'))) {
      n.parentNode.removeChild(n);
}

9.UEditor自定义事件的应用。使用antd的message组件给Ueditor报错。

在ueditor.all.js中,上传失败的时候,触发一个自定义事件:me.fireEvent(‘antdError’, ‘上传失败’);
然后在封装的react组件中监听antdError事件就可以了。

github地址:https://github.com/liusaint/ls-blog/issues/34

你可能感兴趣的:(JavaScript)