基于vue-simplemde实现图片拖拽、粘贴功能
项目使用的是vue框架,需要一个markdown的编辑框,就在npm上找了一下,发现simplemde挺不错的,由于我比较懒,就顺便在npm又搜了一下,找到了 但是这个 拖拽拖拽的API核心是 drop 这个事件,就是当我们从桌面拖动一个文件到浏览器里时,松开的时候,而触发的事件名。 我们都知道,你随便拖动一个图片到浏览器里,会直接打开这个图片,这是因为浏览器默认你拖动文件到浏览器里时,将打开这个文件,所以,我们需要阻止原生的操作。 我们现在先写一段代码,让其屏蔽掉默认事件 {
e = e || event
if (e.target.className === 'CodeMirror-scroll') { // 如果进入到编辑器的话,将阻止默认事件
e.preventDefault()
}
},false)
CodeMirror-scroll 这个Class就是 simplemde 编辑框的Class名称。 现在我们拖拽文件到这个编辑框,然后松掉,不会出现任何反应。如果在编辑框之外的地方,还是会继续触发默认事件。 下面就是获取 simplemde 方法,给他 drop 事件处理方法。 {
simplemde.codemirror.on('drop',(editor,e) => {
if (!(e.dataTransfer && e.dataTransfer.files)) {
// 弹窗说明,此浏览器不支持此操作
return
}
let dataList = e.dataTransfer.files // 循环,是因为可能会同时拖动几个图片文件 诈一看,代码好像有点多,那是因为注释的原因,下面是没有注释的代码。你可以根据下面的代码,有自己的见解和理解: {
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 的时候,是不会发生任何变化的,所以没用必要禁止默认事件。 下面是代码: { // 粘贴图片的触发函数
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 方法进行判断。
if 里的上传图片,不一样的地方是 [dataList[0].getAsFile()] ,因为为了统一格式,方便 uploadImagesFile 函数进行处理,我加上了 [] ,使之成为数组。 dataList[0].getAsFile() 就是获取文件实例了。 上传上传就有一点麻烦了: {
let param = new FormData()
param.append('file',file,file.name)
return param
})
let makeRequest = params => { this.$http.spread = callback => { // 服务端返回的格式是{state: Boolean,data: String} 因为我是把 axiox 封装成vue插件来使用,这样会导致, this.$http 是实例化后的,而不是他本身。 axios 维护者说的解决方案是,重新引入 axios 包,来使用。但是我觉得没有必要。 axios.all 内部是 Promise.all 。 axios.spread 实现代码比较少,就直接拿过来,重新赋值给 axios 就好了 所以上面有段代码是 {
// code
})
把这段代码翻译一下就是 {
// code
})
关于这个问题,请看下官方的解释:。也可以看下 axios 的代码: 这个问题,暂时就不深究了,我们回到刚刚的话题上。 上面我说到当state为true时,data是文件相对于网站的绝对路径,如: /static/upload/2cfd6a50-3d30-11e8-b351-0d25ce9162a3.png 如果我们需要进行拼接一下,所以就有了 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |