克隆DOM元素后如何修复TinyMCE 6内容显示空白问题?
克隆含TinyMCE 6的DOM元素后编辑器内容空白的解决思路
问题场景
项目基于jQuery构建,无法重构。编写了克隆DOM元素的函数,但克隆后的元素中TinyMCE 6编辑器界面加载完成后内容编辑区空白——点击代码视图能看到HTML内容,底层textarea也有内容,但可视化编辑区无显示。
克隆元素函数代码
function duplicateElement($element, dataAttributeName) { var newUniqueId = 'wiz-chunk-' + generateUniqueId(); // Generate a new unique ID //Clone the element var $clonedElement = $element.clone(true, true); $clonedElement.insertAfter($element).addClass('newly-added'); setTimeout(() => $clonedElement.removeClass('newly-added'), 3000); $clonedElement.find('.wiz-wysiwyg').each(function() { var uniqueTextareaId = newUniqueId + '-wiz-wysiwyg'; // New unique ID for the textarea $(this).attr({ 'id': uniqueTextareaId, 'name': newUniqueId + '_wysiwyg_field' }); // Ensure the textarea specifically is visible for TinyMCE initialization //$(this).css('display', 'block'); }); setTimeout(function() { // Update IDs within the cloned element to reflect the new unique ID updateElementIds($clonedElement, $element.attr('id'), newUniqueId); // Reindex data attributes and initialize necessary components reindexDataAttributes(dataAttributeName); initializeChunkSortables(); initializeChunkTabs(); // Initialize TinyMCE on the cloned element builder_init_tinymce($clonedElement); }, 1000); }
TinyMCE初始化函数代码
//Init TinyMCE on each .wiz-wysiwyg element function builder_init_tinymce($optionalElement) { // If an optional jQuery element is provided, find TinyMCE instances within it; otherwise, use the global selector var selector = $optionalElement ? '#' + $optionalElement.attr('id') + ' .wiz-wysiwyg' : '.wiz-wysiwyg'; tinymce.init({ selector: selector, // 其他配置项... }); }
解决思路与代码调整
1. 克隆前销毁原始元素内的TinyMCE实例
clone(true, true)会克隆元素的事件绑定和数据,但TinyMCE的实例与原始textarea强绑定,克隆后会导致新旧实例冲突。克隆前先销毁原始元素里的TinyMCE:
// 在克隆元素前添加: $element.find('.wiz-wysiwyg').each(function() { var editorId = $(this).attr('id'); if (tinymce.get(editorId)) { tinymce.remove(editorId); } }); // 然后再执行克隆: var $clonedElement = $element.clone(true, true);
克隆完成后,重新初始化原始元素的TinyMCE(刚才销毁了),同时初始化克隆元素的。
2. 移除不必要的setTimeout,确保DOM就绪再初始化
固定1000ms的延迟不可靠,改为元素插入DOM后同步处理:
// 替换原来的setTimeout块: $clonedElement.insertAfter($element).addClass('newly-added'); // 直接执行后续逻辑,不需要延迟 updateElementIds($clonedElement, $element.attr('id'), newUniqueId); reindexDataAttributes(dataAttributeName); initializeChunkSortables(); initializeChunkTabs(); // 重新初始化原始元素的TinyMCE builder_init_tinymce($element); // 初始化克隆元素的TinyMCE builder_init_tinymce($clonedElement);
3. 修正初始化函数的选择器逻辑
嵌套选择器可能存在匹配问题,改为直接获取目标textarea的ID列表作为selector:
function builder_init_tinymce($optionalElement) { var selector; if ($optionalElement) { // 收集所有目标textarea的ID,用逗号分隔作为selector selector = $optionalElement.find('.wiz-wysiwyg').map(function() { return '#' + $(this).attr('id'); }).get().join(','); } else { selector = '.wiz-wysiwyg'; } tinymce.init({ selector: selector, // 其他配置项... }); }
4. 手动同步textarea内容到编辑器
如果初始化后内容仍空白,在tinymce的init_instance_callback中手动同步:
tinymce.init({ selector: selector, // 其他配置... init_instance_callback: function(editor) { // 获取对应的textarea元素 var $textarea = $('#' + editor.id); if ($textarea.val()) { editor.setContent($textarea.val()); } } });
5. 避免重复初始化
初始化前检查目标元素是否已有TinyMCE实例,防止冲突:
function builder_init_tinymce($optionalElement) { var targets = $optionalElement ? $optionalElement.find('.wiz-wysiwyg') : $('.wiz-wysiwyg'); targets.each(function() { var editorId = $(this).attr('id'); // 如果已有实例,先移除 if (tinymce.get(editorId)) { tinymce.remove(editorId); } }); var selector = targets.map(function() { return '#' + $(this).attr('id'); }).get().join(','); tinymce.init({ selector: selector, // 其他配置... }); }
内容的提问来源于stack exchange,提问作者Eckstein
相关产品推荐
相关产品推荐

