前後端分離項目中使用富文本編輯器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中導出的有序列表無序列表是這樣的結構:

<ol><li><p></p></li></ol>

導致使用富文本中內容的時候可能會有顯示上的問題。在UEditor源碼找到一個配置參數:
disablePInList: true, //導出有序列表的時候把p標籤去掉
加上之後導出的就是

<ol><li></li></ol>

這樣了。

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

UEditor有一個自動保存的功能,默認會把編輯器中的內容保存到localStorage中。這個功能不需要的話配置enableAutoSave:false可以關閉。
但是要注意1.4的版本這樣配置可能沒有用。 需要到github上下載1.5的版本自己grunt編譯一下使用。

5.百度UEditor編輯器關閉抓取遠程圖片功能 catchRemoteImageEnable: false

測試發現上傳圖片之後再執行一些粘貼操作的時候,原來上傳的圖片全部變成了loading狀態,不能正常顯示。這是因爲對於不同域的圖片,ueditor會嘗試重新上傳到本域,就會出現這樣的情況。

6.輸出過濾。

在圖片上傳中用戶執行提交操作,這個時候取到的富文本內容會包含一個<img class="loadingclass">這樣的loading圖。 這顯然是不合理的。
處理辦法是在contentChange的時候往組件上層傳遞onChange(value)的時候對value進行過濾。
比如使用jq過濾。注意要儘量減少過濾操作。在組件中緩存過濾前的值,如果值沒變,就不去執行過濾,不往上觸發onChange事件。

var html = ueditor.getContent();
var filterdHtml =
    $(`<div>${html}</div>`)
        .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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章