element-tiptap和vuedraggable的拖拽冲突
创始人
2024-03-11 23:42:24
0

今天写项目的时候,遇到一个问题,分享给大家。

场景

我有一个A区域,还有一个B区域。A区域内的Vue组件可以通过Vuedraggable这个框架来拖拽到B区域中。B区域内的Vue组件在标题上使用了element-tiptap组件(用来高级编辑)。然而如果B区与内存在使用了element-tiptap组件的组件。就会出现把 A区域中组件的文本内容拖拽到element-tiptap中。

其实我想要的创建新的组件,而它把我拖拽的组件的文本内容添加到了组件中的element-tiptap中。

问题分析

HTML元素设置了contenteditable="true"之后,或者input输入框之间,默认都是可以把选中的文字拖拽到其他的input的元素或者contenteditable="true"的元素中。

我要做的就是禁止其他页面元素把文本内容拖拽到element-tiptap的组件中,element-tiptap组件的原理就是用的contenteditable="true"来实现高级编辑。

我自己写了一个组件案例,用来验证是否contenteditable="true"的情况下,能通过重写drop事件禁止拖拽:



 自定义组件:DragDiv.vue


实际是生效的,可以通过这种方式来解决这个问题。所以我应该找的是drop事件相关的配置。这里我想了很多方法:

1. 查找element-tiptap 官方文档和源代码,看看有没有相关的组件配置,用来防止其他页面元素拖拽文件进来。onDrop方法前后打印当前的值,结果是相同的,无法解决当前问题。

2. csdn站内包括其他网站的解决方案:把HTML元素的draggable="false",我加上试了没有生效。并没有修改drop事件的处理函数。element-tiptap中自定义了drop事件的处理函数。

3. 实在没办法,只能通过浏览器Debug去分析它的加载流程,包括事件的处理顺序,找到了element-tiptap中,设置contenteditable="true"的div,类名是:ProseMirror,它上面加了两个drop事件的处理函数,对应到它框架代码:

editHandlers.drop = (view, _event) => {let event = _event;let dragging = view.dragging;view.dragging = null;if (!event.dataTransfer)return;let eventPos = view.posAtCoords(eventCoords(event));if (!eventPos)return;let $mouse = view.state.doc.resolve(eventPos.pos);let slice = dragging && dragging.slice;if (slice) {view.someProp("transformPasted", f => { slice = f(slice); });}else {slice = parseFromClipboard(view, event.dataTransfer.getData(brokenClipboardAPI ? "Text" : "text/plain"), brokenClipboardAPI ? null : event.dataTransfer.getData("text/html"), false, $mouse);}let move = !!(dragging && !event[dragCopyModifier]);if (view.someProp("handleDrop", f => f(view, event, slice || Slice.empty, move))) {event.preventDefault();return;}if (!slice)return;event.preventDefault();let insertPos = slice ? dropPoint(view.state.doc, $mouse.pos, slice) : $mouse.pos;if (insertPos == null)insertPos = $mouse.pos;let tr = view.state.tr;if (move)tr.deleteSelection();let pos = tr.mapping.map(insertPos);let isNode = slice.openStart == 0 && slice.openEnd == 0 && slice.content.childCount == 1;let beforeInsert = tr.doc;if (isNode)tr.replaceRangeWith(pos, pos, slice.content.firstChild);elsetr.replaceRange(pos, pos, slice);if (tr.doc.eq(beforeInsert))return;let $pos = tr.doc.resolve(pos);if (isNode && NodeSelection.isSelectable(slice.content.firstChild) &&$pos.nodeAfter && $pos.nodeAfter.sameMarkup(slice.content.firstChild)) {tr.setSelection(new NodeSelection($pos));}else {let end = tr.mapping.map(insertPos);tr.mapping.maps[tr.mapping.maps.length - 1].forEach((_from, _to, _newFrom, newTo) => end = newTo);tr.setSelection(selectionBetween(view, $pos, tr.doc.resolve(end)));}view.focus();view.dispatch(tr.setMeta("uiEvent", "drop"));
};

这里可以看到它的处理流程还是很复杂,我的需求里面没有拖拽文本到B区域中组件的需求,所以这个事件处理函数可以在它的框架代码中删除。

但是项目下有很多的依赖,暂时只能通过如下方法来解决这个问题:(跳过element-tiptap中的drop事件处理函数)

prosemirror-view/dist/index.js:3403行下加入return; 

总结

1. 前端框架的很多高级特性都基于HTML中不常见的属性来实现,在使用框架过程中,应该多去看看它的实现原理,分析关键代码。

2. 编写简洁的代码。

3. 虽然是前端的框架,但是现在很多框架都是用TypeScript来实现,也是有OOP的实践在里面,要多考虑对象的行为和特性,不能把对象属性都暴露,也不能都不暴露。

4. 复用的可能,如果一个框架中组件的复用度不高,引入这个框架,对于项目的后期维护非常不利,想弃用,有依赖 。想重写,需要兼容。

参考:

GitHub - Leecason/element-tiptap: 🌸A modern WYSIWYG rich-text editor using tiptap and Element UI for Vue2 (🚀 tiptap2 and Vue3 is in alpha)

https://github.com/ueberdosis/tiptap

draggable - HTML(超文本标记语言) | MDN

contenteditable - HTML(超文本标记语言) | MDN

欢迎大家私信,留言学习交流。

相关内容

热门资讯

泰柬冲突升级,特朗普劝和无效,... 泰柬边境的战事持续升级,尽管特朗普积极介入调停,但他个人的曝光度并未能改变局势。泰国凭借其强大的军力...
山西省生态环境保护条例自202... 山西省人民代表大会常务委员会公告 (第六十五号) 《山西省生态环境保护条例》已由山西省第十四届人民代...
公安部通报金融领域“黑灰产”违... 12月25日,公安部在京召开专题新闻发布会,通报公安部和国家金融监督管理总局联合部署开展金融领域“黑...
涉案金额近300亿!两部门集群... 公安部25日通报公安部和国家金融监督管理总局联合部署开展金融领域“黑灰产”违法犯罪集群打击情况。聚焦...
岚县公安:多元共治解纠纷 本报讯 近期,岚县公安局社科派出所积极推进“进村入户大走访”专项行动,推动警务下沉、关口前移,联动乡...
“松鼠AI”遭集体诉讼:创始人... 近日,上海市徐汇区人民法院发布的一则开庭公告引发了教育行业高度关注。 该案件的被告是“松鼠AI”母公...
海峡创新:股价波动受多方面因素... 有投资者在互动平台向海峡创新提问:“公司股价严重脱离基本面市净率达80多,多次触发异动炒作,为何公司...
律师、职业催收人为金融黑灰产推... 南都讯记者蒋小天 发自北京 12月25日,公安部举行新闻发布会,通报公安部和国家金融监管总局联合部署...
丽江旅拍协会:将起诉小红书,要... 近日,云南丽江市古城区文化和旅游局公开发布《关于请小红书平台强化丽江市婚拍领域信息审核监管和监测的函...
桃源法院:调解破局“租金困局”... “感谢法庭从中协调,才让事情顺利解决!”当事人感谢说道。 “你是我见过最理解法官的当事人!”桃源县人...