您当前的位置:首页 > 网站建设 > javascript
| php | asp | css | H5 | javascript | Mysql | Dreamweaver | Delphi | 网站维护 | 帝国cms | React | 考试系统 | ajax |

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

51自学网 2022-05-02 21:32:04
  javascript

本文实例为大家分享了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>

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

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


浅析React 对state的理解
JavaScript DOMContentLoaded事件案例详解
51自学网,即我要自学网,自学EXCEL、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。
京ICP备13026421号-1