如何访问CKEditor5操作历史?切换语言版本时历史重置问题求助
解决CKEditor切换多语言文章时重置操作历史的问题
问题根源
使用setData()切换文章语言版本时,CKEditor会完全替换编辑器内容,默认会清空操作历史栈——因为该方法内部执行的是批量不可撤销操作,会直接重置历史记录。
利用History类的getOperations方法保存/恢复历史
CKEditor的History类提供了getOperations()方法,用于获取历史中记录的所有操作,我们可以用它来为不同语言版本缓存各自的操作历史,切换时恢复对应的历史栈。
getOperations方法说明
getOperations(startId = 0)
返回历史中记录的所有操作数组。参数:
- startId:可选数字参数,指定从哪个操作ID开始返回操作,默认值为0(返回全部操作)。
返回值:包含指定范围内所有
Operation对象的数组。
具体实现代码
// 缓存各语言版本的操作历史 const languageHistoryCache = {}; let currentLanguage = 'zh'; // 当前激活的语言 // 保存当前语言的操作历史 function saveCurrentLanguageHistory() { const history = editor.model.history; // 获取全部操作并深拷贝(避免引用导致的缓存污染) const operations = JSON.parse(JSON.stringify(history.getOperations())); languageHistoryCache[currentLanguage] = operations; } // 恢复目标语言的操作历史 function restoreLanguageHistory(targetLang) { const history = editor.model.history; const savedOperations = languageHistoryCache[targetLang]; if (!savedOperations) return; // 先加载目标语言内容(不触发历史记录) editor.model.enqueueChange({ isUndoable: false }, writer => { // 清空当前编辑器内容 const root = editor.model.document.getRoot(); writer.remove(writer.createRangeIn(root)); // 插入目标语言内容(这里替换为你的内容获取逻辑) const targetContent = getArticleContentByLang(targetLang); const modelFragment = editor.data.processor.toModel(targetContent); writer.insertContent(modelFragment, root); }); // 重置当前历史栈并恢复保存的操作 history._operations = []; history._lastOperationId = 0; savedOperations.forEach(op => { // 修正操作ID,保证历史序列连续 op._id = history._lastOperationId + 1; history._operations.push(op); history._lastOperationId = op._id; }); // 更新工具栏撤销/重做按钮状态 const undoButton = editor.ui.view.toolbar.items.get('undo'); const redoButton = editor.ui.view.toolbar.items.get('redo'); if (undoButton) undoButton.isEnabled = history.undoable; if (redoButton) redoButton.isEnabled = history.redoable; } // 切换语言的核心函数 function switchArticleLanguage(newLang) { // 保存当前语言历史 saveCurrentLanguageHistory(); // 更新当前语言标识 currentLanguage = newLang; // 恢复新语言的操作历史 restoreLanguageHistory(newLang); }
注意事项
- 私有属性风险:代码中直接操作了
History类的私有属性(_operations、_lastOperationId),这些属性不属于CKEditor的公开API,后续版本更新可能会导致代码失效,使用时需注意版本兼容性。 - 操作序列化问题:如果操作中包含无法JSON序列化的内容(如DOM节点引用),深拷贝会失败,这种情况下需要自定义拷贝逻辑,只保留操作的核心数据(如操作类型、位置、数据等)。
- 替代方案:如果不想依赖私有API,也可以在切换语言时,将内容替换操作标记为不可撤销(通过
editor.model.enqueueChange({ isUndoable: false }, () => { ... })执行),但这样不同语言的操作历史会混合在一起,仅适用于不需要区分语言历史的场景。
内容的提问来源于stack exchange,提问作者Asen Tahchiyski
相关产品推荐
相关产品推荐

