如何解决JS监听fancybox3 iframe内多CKEditor 5实例变更的报错
CKEditor内容变更监听报错修复方案
错误根源
ClassicEditor.create()是异步Promise方法,初始化过程不会阻塞主线程执行,你在then回调外绑定事件时,编辑器实例还未创建完成,editors[index]处于未赋值的undefined状态,因此读取document属性时报错。- 全局
editors是存储所有编辑器实例的集合对象,本身不存在document属性,因此将监听代码移到外部后依然会触发报错。
修复后代码
以下代码将事件绑定逻辑放到编辑器初始化完成的回调内,同时新增全局修改标记用于对接Fancybox逻辑,CKEditor 5推荐监听change:data事件捕获用户输入变更,触发逻辑更精准:
window.editors = {}; // 全局修改标记,父页面Fancybox可直接读取该变量判断内容状态 window.hasContentChanged = false; document.querySelectorAll( '.editor' ).forEach( ( node, index ) => { ClassicEditor .create( node, { removePlugins: ['Heading', 'BlockQuote', 'CKFinderUploadAdapter', 'CKFinder', 'EasyImage', 'Image', 'ImageCaption', 'ImageStyle', 'ImageToolbar', 'ImageUpload', 'MediaEmbed'], } ) .then( newEditor => { window.editors[ index ] = newEditor; // 编辑器实例创建完成后再绑定事件 newEditor.model.document.on( 'change:data', () => { console.log( 'Alert: The document has changed!, are you sure you want to close without saving?' ); // 标记内容已修改 window.hasContentChanged = true; } ); } ) .catch( error => { console.error( '编辑器初始化失败', error ); } ); } );
Fancybox对接说明
父页面Fancybox 3可以直接读取iframe的全局标记实现关闭提醒、按钮状态修改的需求,配置参考如下:
// 父页面Fancybox 3配置 $.fancybox.open({ src: '你的iframe页面地址', type: 'iframe', // 关闭前触发的回调 beforeClose: function(instance, current) { const iframeWin = current.$iframe[0].contentWindow; // 内容已修改时弹出确认提醒 if (iframeWin.hasContentChanged) { return confirm('你有未保存的修改,确认要关闭吗?'); // 返回false会阻止Fancybox关闭 } } // 其他原有配置项... });
内容保存成功后可以手动将iframe中的window.hasContentChanged重置为false即可消除提醒。
内容的提问来源于stack exchange,提问作者mark-in-motion
相关产品推荐
相关产品推荐

