CKEditor 5中如何实现CKEditor 4自定义内联插件的属性编辑功能?
CKEditor 5 自定义内联Widget迁移方案:优雅更新与回车键拦截
一、优雅更新Widget内容
CKEditor 5 基于模型-视图分离架构,直接替换HTML属于反模式,正确做法是通过修改模型数据实现视图自动同步:
1. 先确保Widget的模型与视图配置正确
首先要给自定义Widget注册模型Schema,并配置双向转换器:
// 1. 注册模型元素 editor.model.schema.register('myWidget', { inheritAllFrom: '$inlineObject', // 内联Widget用这个,块级用$blockObject allowAttributes: ['data-id', 'content', 'custom-prop'] // 定义需要的属性 }); // 2. 模型→视图转换(渲染) editor.conversion.for('downcast').elementToElement({ model: 'myWidget', view: (modelEl, { writer: viewWriter }) => { const widgetView = viewWriter.createInlineElement('span', { class: 'my-inline-widget', 'data-id': modelEl.getAttribute('data-id') }); // 插入Widget内部内容 viewWriter.insert( viewWriter.createPositionAt(widgetView, 0), viewWriter.createText(modelEl.getAttribute('content')) ); return toWidget(widgetView, viewWriter); } }); // 3. 视图→模型转换(比如粘贴时识别) editor.conversion.for('upcast').elementToElement({ view: { name: 'span', classes: 'my-inline-widget' }, model: (viewEl, { writer: modelWriter }) => { return modelWriter.createElement('myWidget', { 'data-id': viewEl.getAttribute('data-id'), 'content': viewEl.getChild(0).data }); } });
2. 修改Widget属性/内容的正确姿势
当用户在弹窗中修改完属性后,直接操作模型元素,编辑器会自动更新视图:
// 示例:打开弹窗并更新Widget function openWidgetSettingsDialog(modelElement) { // 用你的jQuery弹窗获取新属性(比如newId、newContent) const newId = prompt('输入新ID'); const newContent = prompt('输入新内容'); if (newId && newContent) { editor.model.change(writer => { // 更新属性 writer.setAttribute('data-id', newId, modelElement); writer.setAttribute('content', newContent, modelElement); // 如果需要修改内部子节点(比如复杂结构) // writer.remove(modelElement.getChildren()); // writer.appendElement('paragraph', {}, modelElement); }); } }
二、拦截回车键触发自定义操作
通过CKEditor 5的keystrokes API拦截回车键,判断选中的是Widget后触发自定义逻辑并阻止默认行为:
editor.keystrokes.set('Enter', (data, cancel) => { const selectedEl = editor.model.document.selection.getSelectedElement(); // 检查选中的是自定义Widget if (selectedEl && selectedEl.is('element', 'myWidget')) { openWidgetSettingsDialog(selectedEl); // 调用弹窗函数 cancel(); // 阻止默认的插入换行/删除Widget行为 } });
三、双击事件的正确处理
监听视图层的双击事件,映射到模型元素后触发弹窗:
editor.editing.view.document.on('dblclick', (evt, data) => { const viewEl = data.target; const modelEl = editor.editing.mapper.toModelElement(viewEl); if (modelEl && modelEl.is('element', 'myWidget')) { openWidgetSettingsDialog(modelEl); data.preventDefault(); // 阻止默认双击行为 } });
内容的提问来源于stack exchange,提问作者tribalDev
相关产品推荐
相关产品推荐

