自定义拖拽上传文件
嗨,不知道你是否和我一样呢? 想过element-ui的文件拖拽上传是怎么做的? 是怎么监听实时上传进度的呢? 今天就来搞一下,low不low不管,先搞为敬.哈哈1.关于拖住的API1.1在拖动目标上触发事件 (源元素):ondragstart - 用户开始拖动元素时触发ondrag - 元素正在拖动时触发ondragend - 用户完成元素拖动后触发1.2释放目标时触发的事件:ondragent
·
嗨,不知道你是否和我一样呢? 想过element-ui的文件拖拽上传是怎么做的? 是怎么监听实时上传进度的呢? 今天就来搞一下,low不low不管,先搞为敬.哈哈
1.关于拖住的API
1.1在拖动目标上触发事件 (源元素):
- ondragstart - 用户开始拖动元素时触发
- ondrag - 元素正在拖动时触发
- ondragend - 用户完成元素拖动后触发
1.2释放目标时触发的事件:
- ondragenter - 当被鼠标拖动的对象进入其容器范围内时触发此事件
- ondragover - 当某被拖动的对象在另一对象容器范围内拖动时触发此事件
- ondragleave - 当被鼠标拖动的对象离开其容器范围内时触发此事件
- ondrop - 在一个拖动过程中,释放鼠标键时触发此事件
在拖动元素时,每隔 350 毫秒会触发 ondrag 事件
1.3 实现元素拖拽
<p draggable="true" >设置属性后既可以拖动</p>
复制代码
那么知道了基础API,那就让我们来做一个拖拽上传的实例吧: 上上个效果图吧,没图没动力嘛,哈哈
话不多说,先上代码为敬(代码每一行都有注释)
<template>
<div class="index">
<div class="index-box">
<!-- 本地上传进度 -->
<div class="index-progress">
<div class="index-progress-name">本地上传进度:</div>
<div class="index-progress-number">
<el-progress :percentage="scale" :status="scaleName ? scaleName : null "></el-progress>
</div>
</div>
<!-- 拖拽区域 -->
<div class="index-drag"
ref="updataDrag"
@dragover="updataDragover"
@dragenter="updataDragenter"
@dragleave="updataDragleave"
@drop="updateDrop">
<div class="index-drag-iconBox">
<span class="el-icon-upload"></span>
</div>
<div class="index-drag-message">
<span class="index-drag-message-titles">将文件拖动到此处,或</span>
<label for="file" class="index-drag-message-label">
<input class="index-drag-message-input" type="file" id="file" name="file" @change="manualChange" />
<span class="index-drag-message-manual">点击上传</span>
</label>
</div>
</div>
<!-- 本地上传进度 -->
<div class="index-progress">
<div class="index-progress-name">服务器上传进度:</div>
<div class="index-progress-number">
<el-progress :percentage="network" :status="networkName ? networkName : null "></el-progress>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
data(){
return {
scale: 0 ,// 本地上传进度
scaleName: null,
network: 0 , // 网络上传
networkName: null
}
},
methods:{
// 当被拖动的对象在另一对象容器范围内拖动时触发此事件
updataDragover(ev){
// 注意 这里跟关键哈
ev.preventDefault()
},
// 被鼠标拖动的对象进入其容器范围内时触发此事件
updataDragenter(){
this.scaleName = null
// 当被拖拽元素进入 目标区域时, 目标边框变为 蓝色
this.$refs.updataDrag.style.borderColor = '#4B87FF'
this.$refs.updataDrag.style.background = '#F7F7F8'
},
// 当被鼠标拖动的对象离开其容器范围内时触发此事件
updataDragleave(){
// 当被拖拽元素离开 目标区域时, 目标边框变为 灰色
this.$refs.updataDrag.style.borderColor = '#A3A3A3'
this.$refs.updataDrag.style.background = '#ffffff'
},
// 在一个拖动过程中,释放鼠标键时触发此事件
updateDrop(ev){
let oFile = ev.dataTransfer.files[0];
this.readerFile(oFile)
// 这里阻止默认事件 为阻止浏览器自动打开拖拽文件
ev.preventDefault()
},
// 手动上传文件
manualChange(ev){
let oFile = ev.target.files[0]
this.readerFile(oFile)
},
// 读取文件
readerFile(oFile){
let This = this
var reader = new FileReader();
//读取成功
reader.onload = function(ev){
// 以下文件类型判断并不准确,仅入门级,准确的判断 应直接判断 Buffer(这里不再赘述)
// 转 Base64
let txt = ev.target.result;
// 分号位置
let semicolonIndex = txt.indexOf(';')
// 冒号位置
let colonIndex = txt.indexOf(':')
// 文本类型
let txtType = txt.slice(colonIndex + 1,semicolonIndex)
// 详细类型
let types = ''
let format = ''
// 这里 不知道 在Mac下是不是('\')呢? 哈哈
let txtTypeArr = txtType.split('/')
if(txtTypeArr[0] === 'image'){
console.log('图片: 类型为' + txtTypeArr[1])
// Base64 转 图片文件
let images = This.baseImage(txt,'abc.' + txtTypeArr[1])
let params = new FormData()
params.append('file',images) //
This.submitUpdata(params)
}
if(txtTypeArr[0] === 'video'){
console.log('视频: 类型为' + txtTypeArr[1])
let params = new FormData()
params.append('file',oFile) //
This.submitUpdata(params)
}
};
reader.onloadstart = function(){
console.log('读取开始');
This.scaleName = null
};
reader.onloadend = function(){
console.log('读取结束');
This.scaleName = 'success'
};
reader.onabort = function(){
console.log('中断');
This.scaleName = 'exception'
};
reader.onerror = function(){
console.log('读取失败');
This.scaleName = 'warning'
};
reader.onprogress = function(ev){
var scale = ev.loaded/ev.total;
if(scale>=0.5){
reader.abort();
}
// oM.value = scale*100;
This.scale = parseInt(scale*100)
console.log(This.scale)
};
reader.readAsDataURL(oFile); // ,'base64'
},
// Base64 转 图片
baseImage(dataurl, filename) {
let arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type:mime});
},
// 上传
submitUpdata(file){
let This = this
This.networkName = null
axios({
method: 'post',
url: 'https://jsonplaceholder.typicode.com/posts/',
data: file,
headers: {'Content-Type': 'multipart/form-data'},
onUploadProgress:function(progress){
// 上传处理进度事件
let network = parseInt((progress.loaded/progress.total) * 100)
This.network = network
console.log(This.network)
if(progress.loaded == progress.total){
This.networkName = 'success'
}else{
This.networkName = null
}
},
onDownloadProgress:function(progress){
// 为下载处理进度事件
}
})
.then(res => {
// 具体状态码 自行判断 这里用别人的 状态码是 201 哈哈 真实提交不成功哈
if(res.status >= 200 && res.status <= 206){
This.networkName = 'success'
}
if(res.status >= 400){
This.networkName = 'exception'
}
})
}
}
}
</script>
<style scoped>
.index-box{
width: 100%;
height: auto;
padding: 15px;
box-sizing: border-box;
}
.index-progress{
width: 450px;
height: 60px;
/* background: chartreuse; */
margin: 0 auto;
margin-bottom: 15px;
display: flex;
justify-content: space-between;
}
.index-progress-name{
width: 120px;
height: 60px;
font-size: 14px;
font-weight: bold;
line-height: 60px;
/* background: chocolate; */
}
.index-progress-number{
flex: 1;
height: 60px;
padding: 22px;
box-sizing: border-box;
}
.index-drag{
width: 450px;
height: 300px;
border: 2px dashed;
border-color: #A3A3A3;
border-radius: 5px;
margin: 0 auto;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
flex-wrap: wrap;
}
.index-drag-iconBox{
width: 100%;
height: 60px;
/* background: brown; */
text-align: center;
font-size: 50px;
line-height: 60px;
color: #606266;
}
.index-drag-message{
width: 100%;
height: 50px;
line-height: 50px;
text-align: center;
}
.index-drag-message-titles{
font-size: 14px;
color: #606266;
}
.index-drag-message-manual{
font-size: 14px;
color: #4B87FF;
cursor: pointer;
}
.index-drag-message-label{
width: 120px;
height: 50px;
height: auto;
position: relative;
overflow: hidden;
/* background: chartreuse; */
}
.index-drag-message-input{
position: absolute;
left: -100px;
top: -100px;
z-index: -1;
display: none;
}
</style>
复制代码
拓展
- 是否还应该判断 当文件正在上传时,是否阻止其他文件的拓转进入,并给出正在上传的提醒呢?
- 是的需要多文件的拓转上传呢
作者:HTML小白
链接:https://juejin.im/post/5eedb58051882565b60707f0
服务推荐
更多推荐
已为社区贡献1条内容
所有评论(0)