华域联盟 JAVA vue实现拖拽或点击上传图片

vue实现拖拽或点击上传图片

文章目录[隐藏]

本文实例为大家分享了vue实现拖拽或点击上传图片的具体代码,供大家参考,具体内容如下

一、预览图

二、实现

点击上传思路:将input的type设置为“file”类型即可上传文件。隐藏该input框,同时点击按钮时,调取该input的点击上传功能。剩下的就是css优化页面了。

拖拽上传思路:通过给拖拽框dropbox绑定拖拽事件,当组件销毁时解绑事件。在拖拽结束,通过event.dataTransfer.files获取上传的文件信息。然后在对文件进行上传服务器操作。

接下来请允许我简单介绍一下各个组件:

upload.vue封装了点击上传的逻辑,而进度条则没有做,后期可基于percent做参数继续完善进度条;uploadFormDialog.vue是父盒子,即点击上传按钮后弹出的对话框,在该组件中需要完成页面的布局,拖拽上传等逻辑;

这样封装的意义是为了使得代码更便于维护。

upload.vue 点击上传组件

<template>
    <!--upload.vue 点击上传组件 -->
    <div class="file-selector">
        <z-btn class="selector-btn" color="primary" @click="handleUpClick">
            选择文件
        </z-btn>
        <input
            ref="input"
            class="file-selector-input"
            type="file"
            :multiple="multiple"
            :accept="accept"
            @change="handleFiles"
        />
    </div>
</template>
<script>
    import {debounce} from 'lodash/function';
    export default {
        data() {
            return {
                accept: '.jpg,.jpeg,.png,.gif',
                multiple: false,
                list: [], // 已选择的文件对象
                uploadFinished: true, // 上传状态
                startIndex: 0, // 开始上传的下标,用于追加文件
                maxSize: 10 * 1024 * 1024, //10M(size单位为byte)
                // source: this.$axios.CancelToken.source(), // axios 取消请求
            };
        },
        methods: {
            // 重置
            reset() {
                this.list = [];
                this.source.cancel();
                this.startIndex = 0;
                this.uploadFinished = true;
                this.$refs.input && (this.$refs.input.value = null);
            },
            // 调用上传功能
            handleUpClick: debounce(function () {
                // 可在此维护一个上传状态,上传过程中禁用上传按钮
                // if (!this.uploadFinished) this.$message.info('即将覆盖之前的文件~');
                this.$refs.input.click();
            }, 300),
            handleFiles(e) {
                const files = e?.target?.files;
                this.readFiles(files);
            },
            // 上传之前将文件处理为对象
            readFiles(files) {
                if (!files || files.length <= 0) {
                    return;
                }
                for (const file of files) {
                    const url = window.URL.createObjectURL(file);
                    const obj = {
                        title: file.name.replace(/(.*\/)*([^.]+).*/ig, '$2'), // 去掉文件后缀
                        url,
                        file,
                        fileType: file.type,
                        status: 0, // 状态 -> 0 等待中,1 完成, 2 正在上传,3 上传失败
                        percent: 0, // 上传进度
                    };
                    // 提前在 data 中定义 list,用来保存需要上传的文件
                    this.list.unshift(obj);
                    this.$emit('fileList', this.list);
                }
                // 在 data 中定义 startIndex 初始值为 0,上传完成后更新,用于追加上传文件
                // this.startUpload(this.startIndex);
            },

        }
    };
</script>
<style lang="scss">
.file-selector {
    .selector-btn {
        &:hover {
            background-color: rgba($color: #2976e6, $alpha: 0.8);
            transition: background 180ms;
        }
    }

    &-input {
        display: none;
    }
}
</style>

uploadFormDialog.vue 上传对话框

<template>
<!-- 上传dialog -->
<form-dialog
v-model="$attrs.value"
:title="title"
persistent
:loading="loading"
maxWidth="600px"
min-height='400px'
@cancel="handleCancle"
@confirm="handleSubmit"
>
<div
class="d-flex flex-row justify-space-between">
<z-form style='width: 260px; height: 100%;'>
<form-item label="图片名称"  required>
<z-text-field
v-model="formData.name"
outlined
:rules="rules"
:disabled='disabled'
placeholder="请输入图片名称"
>
</z-text-field>
</form-item>
<form-item label="描述" required>
<z-textarea
v-model="formData.description"
outlined
:disabled='disabled'
placeholder="请输入描述"
style="resize: none;"
>
</z-textarea>
</form-item>
</z-form>
<div ref="pickerArea" class="rightBox">
<div  class="uploadInputs d-flex flex-column justify-center align-center" :class="[ dragging ? 'dragging' : '']">
<div ref="uploadBg"  class="uploadBg my-2"></div>
<upload
ref="uploadBtn"
@fileList='fileList'
></upload>
<div class="tip  mt-2">点击上传按钮,或拖拽文件到框内上传</div>
<div class="tinyTip ">请选择不大于 10M 的文件</div>
</div>
</div>
</div>
</form-dialog>
</template>
<script >
import {debounce} from 'lodash/function';
import upload from './upload';
import {uploadImage} from '@/wv-main-admin/apis/image';
export default {
components: {
upload
},
props: ['dialogData'],
data() {
return {
dialogFlag: '',
title: '新增/编辑图片',
loading: false,
formData: {
name: '',
description: ''
},
disabled: false,
rules: [v => !!v || '必填'],
data: {},
dragging: true, //是否拖拽
bindDrop: false,
fileInfo: {},
};
},
mounted() {
},
beforeDestroy() {
// 组件销毁前解绑拖拽事件
try {
const dropbox = this.$refs.pickerArea;
dropbox.removeEventListener('drop', this.handleDrop);
dropbox.removeEventListener('dragleave', this.handleDragLeave);
dropbox.removeEventListener('dragover', this.handleDragOver);
this.bindDrop = false;
} catch (e) { console.log(e, '======我是组件销毁前解绑拖拽事件的异常'); }
},
methods: {
//取消
handleCancle() {
// 关闭当前弹框
this.$emit('input', false);
// 强制组件刷新
this.$forceUpdate();
},
handleSubmit: debounce(function () {
// 上传单个文件
const flag = this.checkMustsItem();
if (flag) {
this.startUpload();
// 上传完成,强制组件刷新
this.$forceUpdate();
}
}, 300),
//监听子组件的值
fileList(data) {
this.fileInfo = data[0];
this.formData.name = this.fileInfo.title;
const uploadBg = this.$refs.uploadBg;
//改变背景图片
uploadBg.style.backgroundImage = `url(${this.fileInfo.url})`;
},
bindEvents() {
const dropbox = this.$refs.pickerArea;
// 防止重复绑定事件,需要在 data 中初始化 bindDrop 为 false
if (!dropbox || this.bindDrop) { return; }
// 绑定拖拽事件,在组件销毁时解绑
dropbox.addEventListener('drop', this.handleDrop, false);
dropbox.addEventListener('dragleave', this.handleDragLeave);
dropbox.addEventListener('dragover', this.handleDragOver);
this.bindDrop = true;
},
// 拖拽到上传区域
handleDragOver(e) {
e.stopPropagation();
e.preventDefault();
this.dragging = true;
},
// 离开上传区域
handleDragLeave(e) {
e.stopPropagation();
e.preventDefault();
this.dragging = false;
},
// 拖拽结束
handleDrop(e) {
e.stopPropagation();
e.preventDefault();
this.dragging = false;
const files = e.dataTransfer.files;
// 调用 <upload/> 组件的上传功能
this.$refs.uploadBtn && this.$refs.uploadBtn.readFiles(files);
},
// 上传前需要校验文件
checkFile(index) {
const file = this.list[index];
// 如果文件不存在,即全部文件上传完成
if (!file) {
// 上传完成,向父组件抛出 success 事件
this.uploadFinished = true;
this.$emit('success', this.list);
// 清空上传控件中的值,保证 change 事件能正常触发
this.$refs.input.value = null; this.startIndex = index > 1 ? index - 1 : 0;
return false;
}
// 校验是否已上传
if (`${file.status}` === '1') {
this.startUpload(++index);
return false;
}
// 校验文件大小
if (this.maxSize && file.file && file.file.size >= this.maxSize) {
this.startUpload(++index);
return false;
}
return true;
},
checkMustsItem() {
if (!this.fileInfo.file) {
this.$message.warning('请上传文件!');
return false;
} if (!this.formData.name) {
this.$message.warning('请输入文件名称!');
return false;
} if (!this.formData.description) {
this.$message.warning('请输入文件描述!');
return false;
}
return true;
},
// 上传单个文件
startUpload() {
this.loading = true;
const params = {
type: 'image'
};
this.$set(params, 'file', this.fileInfo.file);
this.$set(params, 'name', this.formData.name);
this.$set(params, 'description', this.formData.description);
uploadImage(params)
.then(res => {
this.loading = false;
if (res.code === 0) {
this.$message.success('上传成功~');
this.$emit('refreshList', false);
this.$emit('input', false);
}
})
.catch(() => {
this.loading = false;
});
// this.$axios({
//     url: this.url, // 上传接口,由 props 传入
//     method: 'post',
//     data,
//     withCredentials: true,
//     cancelToken: this.source.token, // 用于取消接口请求
//     // 进度条
//     onUploadProgress: e => {
//         if (fileObj.status === 1) { return; } // 已上传
//         // 限定最大值为 99%
//         const p = parseInt((e.loaded / e.total) * 99);
//         if (e.total) {
//             fileObj.status = 2; // 正在上传
//             fileObj.percent = p; // 更新上传进度
//         } else {
//             fileObj.status = 3; // 上传失败
//         }
//     },
// })
//     .then(response => {
//         if (`${response.code}` === '200') {
//             fileObj.status = 1;
//             fileObj.percent = 100;
//         } else {
//             fileObj.status = 3;
//         }
//     })
//     .catch(e => {
//         console.log(e, '====error');
//         fileObj.status = 3;
//     })
//     .finally(e => {
//         console.log(e, '====error');
//         this.startUpload(++index);
//     });
// 上传完成
},
},
};
</script>
<style lang='scss' scoped>
.rightBox {
width: 260px;
height: 250px;
border: 1px solid #ccc;
margin-top: 18px;
.uploadBg {
width: 150px;
height: 125px;
background: url("../../../../assets/upload.png") no-repeat center center;
background-size: contain;
}
.tip {
font-size: 13px;
color: rgba(0, 0, 0, 0.87);
}
.tinyTip {
font-size: 12px;
color: #8e8f9e;
}
}
</style>

注:以上代码用到了我们自己封装的组件库和自己封装的一些方法,请根据具体场景进行相关的修改。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持华域联盟。

您可能感兴趣的文章:

本文由 华域联盟 原创撰写:华域联盟 » vue实现拖拽或点击上传图片

转载请保留出处和原文链接:https://www.cnhackhy.com/81189.htm

本文来自网络,不代表华域联盟立场,转载请注明出处。

作者: sterben

发表回复

联系我们

联系我们

2551209778

在线咨询: QQ交谈

邮箱: [email protected]

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部