如何找到对应位置的源码。 目前我是无法直接找到的, 我是通过搜索网上的答案或者 debugger 才能够对应源码, 我做不到短时间内了解一个库的完全流程,所以看我文章的人也不必焦虑。慢慢debugger 了解部分源码就行
quill 为什么粘贴图片时为 base64
项目使用的版本是1.3.7
quilljs/quill at 1.3.7 (github.com)
https://github.com/quilljs/quill/blob/0148738cb22d52808f35873adb620ca56b1ae061/modules/clipboard.js#L60
1
| this.quill.root.addEventListener('paste', this.onPaste.bind(this));
|
https://github.com/quilljs/quill/blob/0148738cb22d52808f35873adb620ca56b1ae061/modules/clipboard.js#L108
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| onPaste(e) { if (e.defaultPrevented || !this.quill.isEnabled()) return; let range = this.quill.getSelection(); let delta = new Delta().retain(range.index); let scrollTop = this.quill.scrollingContainer.scrollTop; this.container.focus(); this.quill.selection.update(Quill.sources.SILENT); setTimeout(() => { delta = delta.concat(this.convert()).delete(range.length); this.quill.updateContents(delta, Quill.sources.USER); this.quill.setSelection(delta.length() - range.length, Quill.sources.SILENT); this.quill.scrollingContainer.scrollTop = scrollTop; this.quill.focus(); }, 1); }
|
粘贴的时候核心代码在这上面。
#1
1 2 3 4 5 6 7 8 9 10 11
| <div class="container"> <div class="editor" contenteditable="true" style="width: 200px;height: 200px;"></div> <div class="clipboard" contenteditable="true"></div> </div> <script> const editorEl = document.querySelector('.editor'); const clipboardEl = document.querySelector('.clipboard') editorEl.addEventListener('paste', () => { clipboardEl.focus() }) </script>
|
匹配到了这段代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function matchBlot(node, delta) { var match = _parchment2.default.query(node); if (match == null) return delta; if (match.prototype instanceof _parchment2.default.Embed) { var embed = {}; var value = match.value(node); if (value != null) { embed[match.blotName] = value; delta = new _quillDelta2.default().insert(embed, match.formats(node)); } } else if (typeof match.formats === 'function') { delta = applyFormat(delta, match.blotName, match.formats(node)); } return delta; }
|
获取剪贴板里面的元素转换为 delta。然后将剪贴板的元素情况。 更新quill 里面的内容。就将图片插入进去了。
回到为什么是 base64图片。 原因就在于浏览器粘贴的时候用的就是 base64.🥳
是不是有点废话。这一段分析是为了下面处理图片做铺垫的~
粘贴图片上传图片
Clipboard Module - Quill Rich Text Editor (quilljs.com)
quill 已经提供了接口。 所以我们只需要配置一下就可以了, 在 quill 的 option 里面做如下配置。 不只是粘贴图片。 quill的 toolbar 也有一个上传图片的功能。可以通过 options 里的handles 配置,这里不讨论。
1 2 3 4 5 6
| clipboard: { matchers: [ ['img', this.noPastingPictures], ], },
|
noPastingPictures(上传 base64图片) 部分代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| noPastingPictures(node, delta) { const urlReg = /^https?:\/\/(([a-zA-Z0-9_-])+(\.)?)*(:\d+)?(\/((\.)?(\?)?=?&?[a-zA-Z0-9_-](\?)?)*)*$/i; if (delta && delta.ops) { delta.ops.forEach(item => { if (item.insert && item.insert.image) { if (item.insert.image.includes('data:image')) { this.handleBase64Image(item); } else if (!urlReg.test(item.insert.image)) { this.imageError(); } } }); } return delta; }, handleBase64Image(data) { const { image } = data.insert; try { const file = this.dataURItoBlob(image); file.name = new Date().getTime(); this.copyPicture(image, file); } catch { this.imageError(); } }, async copyPicture(image, file) { this.loadingCount++; try { const fileUrl = await (new FileUpload()) .uploadStart([file]); await this.loadImage(fileUrl[0].url);
this.content = this.content.replace(image, fileUrl[0].url); } catch { this.$message.error('图片上传失败'); } finally { this.loadingCount--; } }, imageError() { this.$message.error('粘贴图片失败。请单独选中原图复制粘贴'); }, loadImage(url) { const image = new Image(); return new Promise((resolve, reject) => { image.onload = resolve; image.onerror = reject; image.src = url; }); },
|
粘贴图片的时候你会发现 windows 从资源管理器里面粘贴的图片不显示。macos11从资源管理器里面粘贴的图片是一个文件图标,但是 macos12正常。 这就是系统上面的处理方法不同的。如果需要兼容从资源管理器里面粘贴图片。 可以自定义 quill 的 paste 事件。 读取对应的 paste 数据。转成图片。我选择的是通过拖动图片进行处理
拖动图片上传
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| bindDropEvent() { const quillEl = this.$refs.quill.quill.root; quillEl.addEventListener('drop', this.dropHandle, false); this.$once('hook:beforeDestroy', () => { quillEl.removeEventListener('drop', this.dropHandle); }); }, dropHandle(e) { e.preventDefault(); if (!e.dataTransfer.files.length) { return; }
const file = e.dataTransfer.files[0]; const type = file.type.split('/')[0]; if (type !== 'image') { return; } this.copyPicture(file); },
|
是从 vue项目代码里面拷贝过来的,将就看一下。 大概流程是拖动图片获取对应的数据, 上传然后插入。这里有个 bug,就是编辑器里面没有内容的时候, 需要focusc才能插入。而且会插入一个空行。
第三方解决方案
[EthanYan6/quill-image-super-solution-module: quill,image,upload,paste,drop,extend…]功能最全!实现最完美!体积最小!解决同类型插件的所有bug!此模块为富文本编辑器 vue-quill-editor 的专用插件,为其提供了自定义上传图片到服务器、粘贴图片上传至服务器、拖拽图片上传至服务器的功能。支持与其他模块一起使用。 (github.com)
这是我在 github 上面找的。
我觉得这个库有一点可以优化, 就是自定义上传函数。 而不是通过库去请求上传地址。