百度ueditor 實例化 Cannot set property 'innerHTML' of null 完美解決方案

此時此刻,我正在用博客園推薦的TinyMCE編輯器寫這個博客,忽然想起最近在項目中使用百度ueditor編輯器中的一些經歷.因此記錄在此,與你們分享.javascript

不得不說,百度ueditor是一款很好的在線編輯器,爲開發者提供了諸多便利,你甚至能夠用它來把word文檔的內容按照必定的格式轉換成html代碼,而後再放進本身的項目中.php

1.咱們的項目中,用戶在註冊時有可能須要查看用戶協議和隱私協議,而咱們的文案是將這兩個協議的內容放在word文檔中,做爲苦逼的開發人員,你須要把這些文字展現在html頁面上,而且保持必定的樣式,例如首行縮進,行距等等;html

這裏有兩個解決方案:java

第一種------word文檔能夠直接轉換成html.不錯,是有這個功能,可是通過本人親測,2010版本的並很差用,可是word2003還不錯.瀏覽器

第二種------我當時採用的方法就是利用word與notepad++協做調好文檔的格式,再將調好格式的文檔內容拷貝到ueditor編輯器.生成html代碼,而後C V大法,扔進須要展現的html頁面,在瀏覽器預覽進行微調就能夠了.至於怎麼生成html代碼,你能夠看到博客園TinyMCE編輯器的工具欄處,有一個寫有html的按鈕.ueditor也如此,點擊便可生成html代碼,編輯器

這兩種方法,請你們自行去比較哪一種方便,哪一種適合你.....函數

2.該說說今天這篇博客的主題了,那就是在使用ueditor時,實例化編輯器遇到的問題.工具

來到百度ueditor官網,下載一個你須要的版本(java,php等),頁面頭部引入以下標籤,ui

<script type="text/javascript" charset="utf-8" src="ueditor.config.js"></script>
<script type="text/javascript" charset="utf-8" src="ueditor.all.js"> </script>//這裏爲了方便看源碼,就不引用min.js了
<script type="text/javascript" charset="utf-8" src="lang/zh-cn/zh-cn.js"></script>lua

而後在html body標籤裏面寫下以下代碼,你的ueditor應該就實例化成功了(個人頁面上有至少2個ueditor編輯器,先將它定義爲編輯器頁面)

<body>

<script id="editor" type="text/plain" style="width:1024px;height:500px;"></script>

<script id="editor1" type="text/plain" style="width:1024px;height:500px;"></script>

<script>

     var editor=UE.getEditor('')

     var editor1=UE.getEditor('')

</script>

</body>

隨後,當我在第一次進入該頁面時,採用編輯器內置的方法setContent,給編輯器設置初始值(成功了):

editor.ready(function(){//監聽編輯器實例化完成的事件

console.log('編輯器1實例化完成')

editor.setContent('嘿嘿')

})

editor.ready(function(){

console.log('編輯器2實例化完成')

editor1.setContent('哈哈')

})

可是當我點擊瀏覽器的後退鍵返回上一個頁面(或者是點擊頁面上本身設置的後退按鈕返回上一個頁面)後,再一次進入到編輯器頁面,一樣調用

editor.setContent('嘿嘿')

editor1.setContent('哈哈')

的方法,瀏覽器控制檯就報錯了 Cannot set property 'innerHTML' of null .意思就是須要賦值的對象是null(但爲何沒有報undefined呢?答案接下來分析)

並且奇葩的是,editor編輯器內容賦值成功,可是editor1賦值失敗.

思前想後,仍是去看看ueditor的源碼吧.

UE.getEditor = function (id, opt) {
var editor = instances[id];
if (!editor) {
editor = instances[id] = new UE.ui.Editor(opt);
editor.render(id);
}
return editor;
};
源碼裏的instances是一個初始化的空對象

代碼的意思就是:先去頁面找是否存在已經實例化的編輯器對象,若是沒有,就新生成一個編輯器.不然直接將頁面上找到的那個編輯器給返回.再聯想到剛纔的報錯Cannot set property 'innerHTML' of null(而不是undefined,並且控制檯也沒有輸出編輯器2實例化完成),那麼真相只有一個! 那就是當你在一次來到編輯器頁面時,編輯器早已經存在,都已經存在的編輯器,天然不會觸發ready事件,因此天然不能觸發卸載ready事件裏的setContent事件了.

好奇的小夥伴必定會想到,既然編輯器已經存在了,那麼咱們把setContent函數調到ready事件外,不就好了嗎!!!!  然而,並無任何luan用.....(設置setTimeout也不行)

按照個人猜測,此時當你第二次或者第三第四....次進入編輯器頁面,雖然頁面上存在這第一次你進入該頁面時的那個實例化好的編輯器,可是如今的它,功能並不完整了,你能夠理解成汽車沒了發動機,殘疾了哎.

好了,找到了問題的根本,那麼咱們就來解決問題吧,方法也有兩個:

1.個人頁面既然有返回的按鈕,那麼我只須要在每次點擊返回的時候,將頁面上的ueditor對象銷燬了,這樣一來,下次再進入到此頁面,就會從新實例化一個功能健全的ueditor了,

2.上面的解決辦法是從表象上去組織可能錯誤的發生,能夠說是治標不治本,由於一些用戶的操做習慣是直接點擊瀏覽器的後退按鈕回到上一個頁面,下次進入到編輯器頁面,一樣會遇到以前的問題.固然你們也能夠利用js動態去判斷瀏覽器的地址,從而決定應該什麼時候銷燬編輯器對象,相信這個方法也是能夠的.

不過我想說的是,咱們就來點簡單粗暴的方法吧,ok,再回到ueditor源碼

UE.getEditor = function (id, opt) {
var editor = instances[id];
if (!editor) {
editor = instances[id] = new UE.ui.Editor(opt);
editor.render(id);
}
return editor;
};

咱們能夠跳過上面代碼的判斷,每一次直接根據js傳來的id,生成一個全新的ueditor對象.因此上述代碼能夠改爲:

UE.getEditor = function (id, opt) {

UE.delEditor(id);
var editor = new UE.ui.Editor(opt);
editor.render(id);
return editor;
};

最後附上銷燬ueditor的一個方法:(UE.delEditor('editor'))

UE.delEditor = function (id) {
var editor;
if (editor = instances[id]) {
editor.key && editor.destroy();
delete instances[id]
}
};

最後與你們共勉一句話:每當你擼代碼累了的時候,想一想你上次解決困擾已久的bug的那種快感吧~

相關文章
相關標籤/搜索