今回は、vue-simplemde で画像をドラッグ&ペーストする際の注意点を紹介します。実際の事例を見てみましょう。
しかし、この vue-simplemde
は画像のドラッグ アンド ドロップ アップロードや貼り付けアップロードをサポートしていません。また、vue-simplemde は単なる Vue プラグインであるため、これが vue-simplemde のせいであるとは言えません。 simplemde に基づいています。結局のところ、simplemde が関連する機能を提供していないためですが、ユーザーエクスペリエンスのために、マークダウンエディターを使用しない場合を除き、この機能は必要です。代わりに、リッチ テキスト エディタを使用してください。その場合、プロジェクト内の多くのコードを変更する必要があります。そこで、オンラインの記事と github 上のコードを確認しました。以下が分析されます vue-simplemde
不支持图片拖拽上传、粘贴上传,也不能说是因为这个 vue-simplemde ,因为 vue-simplemde 只是对 simplemde 的基础上封装成一个Vue插件。所以最后还是由于 simplemde 没有提供相关的功能,但是为了用户体验考虑,这个功能时必要的,除非不使用markdown编辑器。而去使用富文本编辑器,那样的话,项目很多的代码都要进行更改。所以就在网上查了文章,及在github上查了一些代码。下面将进行分析
拖拽
拖拽的API核心是 drop 这个事件,就是当我们从桌面拖动一个文件到浏览器里时,松开的时候,而触发的事件名。
我们都知道,你随便拖动一个图片到浏览器里,会直接打开这个图片,这是因为浏览器默认你拖动文件到浏览器里时,将打开这个文件,所以,我们需要阻止原生的操作。
我们现在先写一段代码,让其屏蔽掉默认事件
window.addEventListener("drop", e => { e = e || event if (e.target.className === 'CodeMirror-scroll') { // 如果进入到编辑器的话,将阻止默认事件 e.preventDefault() } }, false)
CodeMirror-scroll 这个Class就是 simplemde 编辑框的Class名称。
现在我们拖拽文件到这个编辑框,然后松掉,不会出现任何反应。如果在编辑框之外的地方,还是会继续触发默认事件。
下面就是获取 simplemde 方法,给他 drop 事件处理方法。
// 假设页面一共有三个编辑窗口,所以需要循环监听事件 [ this.$refs.simplemde1, this.$refs.simplemde2, this.$refs.simplemde3 ].map(({simplemde}) => { simplemde.codemirror.on('drop', (editor, e) => { if (!(e.dataTransfer && e.dataTransfer.files)) { // 弹窗说明,此浏览器不支持此操作 return } let dataList = e.dataTransfer.files let imageFiles = [] // 要上传的文件实例数组 // 循环,是因为可能会同时拖动几个图片文件 for (let i = 0; i < dataList.length; i++) { // 如果不是图片,则弹窗警告 仅支持拖拽图片文件 if (dataList[i].type.indexOf('image') === -1) { // 下面的continue,作用是,如果用户同时拖动2个图片和一个文档,那么文档不给于上传,图片照常上传。 continue } imageFiles.push(dataList[i]) // 先把当前的文件push进数组里,等for循环结束之后,统一上传。 } // uploadImagesFile方法是上传图片的方法 // simplemde.codemirror的作用是用于区分当前的图片上传是处于哪个编辑框 this.uploadImagesFile(simplemde.codemirror, imageFiles) // 因为已经有了下面这段代码,所以上面的屏蔽默认事件代码就不用写了 e.preventDefault() }) })
诈一看,代码好像有点多,那是因为注释的原因,下面是没有注释的代码。你可以根据下面的代码,有自己的见解和理解:
[ this.$refs.simplemde1, this.$refs.simplemde2, this.$refs.simplemde3 ].map(({simplemde}) => { simplemde.codemirror.on('drop', (editor, e) => { if (!(e.dataTransfer && e.dataTransfer.files)) { return } let dataList = e.dataTransfer.files let imageFiles = [] for (let i = 0; i < dataList.length; i++) { if (dataList[i].type.indexOf('image') === -1) { continue } imageFiles.push(dataList[i]) } this.uploadImagesFile(simplemde.codemirror, imageFiles) e.preventDefault() }) })
粘贴
粘贴的API是 paste 方法,这个不像上面一样,粘贴不需要禁止默认事件,因为我们可以看到,你复制一个图片,到浏览器里按下 ctrl+v 的时候,是不会发生任何变化的,所以没用必要禁止默认事件。
下面是代码:
simplemde.codemirror.on('paste', (editor, e) => { // 粘贴图片的触发函数 if (!(e.clipboardData && e.clipboardData.items)) { // 弹窗说明,此浏览器不支持此操作 return } try { let dataList = e.clipboardData.items if (dataList[0].kind === 'file' && dataList[0].getAsFile().type.indexOf('image') !== -1) { this.uploadImagesFile(simplemde.codemirror, [dataList[0].getAsFile()]) } } catch (e) { // 弹窗说明,只能粘贴图片 } })
之所以这里写上 try...catch 方法,是因为如果你粘贴的时候,如果是一个文件, items 将是空的,而在下面的if循环里,使用 dataList[0].kind 。也就是 e.clipboardData.items[0].kind 。当 item 为空时,还去访问一个不存的 kind 属性时,就会报错了。所以这里需要使用 try...catch 方法进行判断。
dataList[0].getAsFile().type.indexOf('image') !== -1
ドラッグ アンド ドロップ API の中核は、デスクトップからブラウザにファイルをドラッグして放したときにトリガーされるイベントの名前であるドロップ イベントです。それ。
画像をブラウザにドラッグすると、その画像が直接開かれることは誰もが知っています。これは、ファイルをブラウザにドラッグするとデフォルトでファイルが開かれるためです。そのため、ネイティブ操作を防ぐ必要があります。 デフォルトのイベントをブロックするコードを書いてみましょうuploadImagesFile (simplemde, files) { // 把每个文件实例使用FormData进行包装一下,然后返回一个数组 let params = files.map(file => { let param = new FormData() param.append('file', file, file.name) return param }) let makeRequest = params => { return this.$http.post('/Api/upload', params) } let requests = params.map(makeRequest) this.$http.spread = callback => { return arr => { return callback.apply(null, arr) } } // 服务端返回的格式是{state: Boolean, data: String} // state为false时,data就是返回的错误信息 // state为true时,data是图片上传后url地址,这个地址是针对网站的绝对路径。如下: // /static/upload/2cfd6a50-3d30-11e8-b351-0d25ce9162a3.png Promise.all(requests) .then(this.$http.spread((...resps) => { for (let i = 0; i < resps.length; i++) { let {state, data} = resps[i].data if (!state) { // 弹窗显示data的错误信息 continue } let url = `![](${location.origin + data})` // 拼接成markdown语法 let content = simplemde.getValue() simplemde.setValue(content + url + '\n') // 和编辑框之前的内容进行拼接 } })) }
Promise.all(requests) .then(this.$http.spread((...resps) => { // code })
axios.all(requests) .then(axios.spread((...resps) => { // code })
ペースト用の API は、上記とは異なり、デフォルトのイベントを無効にする必要はありません。画像をコピーしてブラウザで Ctrl+V を押しても何も変わらないことがわかるため、デフォルトのイベントを無効にする必要はありません。 以下はコードです:
rrreee
dataList[0].getAsFile().type.indexOf('image') !== -1
この文は、貼り付けられたものは画像であり、別のものではないことが確認されています。 。 🎜🎜ifでの画像アップロードの違いは[dataList[0].getAsFile()]ですが、形式を統一してuploadImagesFile関数での処理を容易にするために[]を付けて配列にしたためです。 dataList[0].getAsFile()はファイルインスタンスを取得します。 🎜🎜🎜🎜アップロード🎜🎜🎜🎜アップロードは少し面倒です: 🎜rrreee🎜 axiox を vue プラグインとしてカプセル化して使用しているため、これにより this.$http 自体ではなくインスタンス化されます。 axios メンテナーが提案する解決策は、axios パッケージを再導入して使用することです。しかし、私はそれが必要だとは思いません。内部的には axios.all は Promise.all です。 axios.spread の実装コードは比較的小さいので、それを取得して axios に再割り当てするだけです🎜🎜したがって、上記のコードは🎜rrreee🎜このコードを翻訳すると、次のようになります🎜rrreee🎜 ケースを読んだ後、あなたはそれをマスターしたと思いますこの記事の「方法」では、さらに興味深い情報については、php 中国語 Web サイトの他の関連記事に注目してください。 🎜🎜推奨読書: 🎜🎜🎜vuex ページが更新された後にデータを保存できない場合の対処方法🎜🎜🎜🎜🎜実践的なプロジェクトで Vue2.0 ラジオ選択を相互に排他的にする方法🎜🎜🎜以上がvue-simplemde で画像をドラッグ&ペーストできるようになりますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。