前提:wangeditor版本:4.7.11? ? ?vue版本:vue2?
問題:在使用wangeditor富文本編輯器時,需求需要通過點擊一個按鈕,手動插入定義好的內容,所以使用了 editor.cmd.do('insertHTML', '....') 方法新增內容。但當頁面使用keep-alive緩存后,切換到其他頁面再切換回編輯器,此時直接調用手動插入內容,Console報錯:Uncaught TypeError: Cannot read properties of undefined (reading 'parentNode')
解決:
方式一:可以發現,如果手動點擊編輯器,使光標置于編輯器內,再通過 editor.cmd.do() 方法插入內容是不會出錯的,但嘗試手動設置focus后并未解決問題。于是通過檢測錯誤,提示用戶手動確認插入位置,但因為錯誤發生在插入編輯器時,前置的一些請求等操作已經發生了,所以在這兒做一些額外的業務操作:比如調用接口刪除數據庫中剛剛未成功插入的內容等。
public activated() {window.addEventListener('error', this.watchErrorEvent);
}public deactivated() {window.removeEventListener('error', this.watchErrorEvent);
}public watchErrorEvent() {const msg = error.message;if(error.message.includes('Uncaught TypeError') &&error.message.includes(`'parentNode'`)) {this.$Message.info('請確認插入位置!');// 額外操作......}
}
方式二:方式一其實并未真正解決問題,現在從代碼層面去分析和查找問題所在。
分析:
- 首先定位發生錯誤的代碼:提示在geDom方法中的 var $parent = dom_core_1["default"]($node, parentNode) 出錯,一頓操作后,好吧我沒找出來原因。
- 那就直接查看 editor.cmd.do() 方法內部,通過debugger對比正常調用和調用出錯的情況,發現selection._currentRange中的值不同。
- 查看selection的內容:查看源碼 wangeditor/src/editor/selection.ts 中的?selection._currentRange,發現?_currentRange 是私有屬性,并且在 saveRange(range?:Range) 方法中賦值的。
- 既然 _currentRange 是私有屬性,我們就不好直接修改,而且用于賦值的range是通過Selection對象得到的range對象,那么猜測是選區出錯,那有方式可以重新設置一下selection嗎?發現 index.ts 中,有一個初始化選區的方法,查看調用的 initSelection() 方法的作用是 初始化編輯器選區,將光標定位到文檔末尾。感覺就是它了!
- 在組件的activated函數中調用此方法,測試后發現未報錯了,內容也成功插入。
最終代碼:
public activated() {// this.editor = new Editor(...) 對象if(this.editor) {this.editor.initSelection();}
}