zoukankan      html  css  js  c++  java
  • Vue上传图片预览组件

      父组件:

    <template>
        <div>
            <h4>基于Vue.2X的html5上传图片组件</h4>
            <div style=" 502px;">
                <uploader :src="'/api/imgsupload'"></uploader>
            </div>
        </div>
    </template>
    <script>
        import uploader from './uploader.vue'
        export default {
            data() {
                return {}
            },
            components: {
                uploader
            }
        }
    </script>

      子组件:

    <template>
        <div class="vue-uploader">
            <div class="file-list">
                <section v-for="(file, index) of files" class="file-item draggable-item">
                    <img :src="file.src" alt="" ondragstart="return false;">
                    <p class="file-name">{{file.name}}</p>
                    <span class="file-remove" @click="remove(index)">+</span>
                </section>
                <section v-if="status == 'ready'" class="file-item">
                    <div @click="add" class="add">
                        <span>+</span>
                    </div>
                </section>
            </div>
    
            <section v-if="files.length != 0" class="upload-func">
                <div class="progress-bar">
                    <section v-if="uploading" :width="(percent * 100) + '%'">{{(percent * 100) + '%'}}</section>
                </div>
                <div class="operation-box">
                    <button v-if="status == 'ready'" @click="submit">上传</button>
                    <button v-if="status == 'finished'" @click="finished">完成</button>
                </div>
            </section>
            <input type="file" accept="image/*" @change="fileChanged" ref="file" multiple="multiple">
        </div>
    </template>
    <script>
        export default {
            props: {
                src: {
                    type: String,
                    required: true
                }
            },
            data() {
                return {
                    status: 'ready',
                    files: [],
                    uploading: false,
                    percent: 0
                }
            },
            methods: {
                add() {
                    this.$refs.file.click()//调用file的click事件
                },
                submit() {
                    if (this.files.length === 0) {
                        console.warn('no file!');
                        return
                    }
                    //当点击上传按钮时,将会遍历所有选中的文件,并添加到自定义的FormData中
                    const formData = new FormData()
                    this.files.forEach((item) => {
                        formData.append(item.name, item.file)
                    })
                    const xhr = new XMLHttpRequest()
                    xhr.upload.addEventListener('progress', this.uploadProgress, false)
                    xhr.open('POST', this.src, true)
                    this.uploading = true
                    xhr.send(formData)
                    xhr.onload = () => {
                        this.uploading = false
                        if (xhr.status === 200 || xhr.status === 304) {
                            this.status = 'finished'
                            console.log('upload success!')
                        } else {
                            console.log(`error:error code ${xhr.status}`)
                        }
                    }
                },
                finished() {
                    this.files = []
                    this.status = 'ready'
                },
                remove(index) {
                    this.files.splice(index, 1)
                },
                fileChanged() {
                    const list = this.$refs.file.files
                    for (let i = 0; i < list.length; i++) {
                        if (!this.isContain(list[i])) {
                            const item = {
                                name: list[i].name,
                                size: list[i].size,
                                file: list[i]
                            }
                            this.html5Reader(list[i], item)
                            this.files.push(item)
                        }
                    }
                    this.$refs.file.value = ''
                },
                // 将图片文件转成BASE64格式
                html5Reader(file, item){
                    const reader = new FileReader()
                    reader.onload = (e) => {
                        this.$set(item, 'src', e.target.result)
                    }
                    reader.readAsDataURL(file)
                },
                isContain(file) {
                  return this.files.find((item) => item.name === file.name && item.size === file.size)
                },
                uploadProgress(evt) {
                    const component = this
                    if (evt.lengthComputable) {
                        const percentComplete = Math.round((evt.loaded * 100) / evt.total)
                        component.percent = percentComplete / 100
                    } else {
                        console.warn('upload progress unable to compute')
                    }
                }
            }
        }
    </script>
    <style>
    .vue-uploader {
        border: 1px solid #e5e5e5;
    }
    .vue-uploader .file-list {
        padding: 10px 0px;
    }
    .vue-uploader .file-list:after {
        content: '';
        display: block;
        clear: both;
        visibility: hidden;
        line-height: 0;
        height: 0;
        font-size: 0;
    }
    .vue-uploader .file-list .file-item {
        float: left;
        position: relative;
         100px;
        text-align: center;
    }
    .vue-uploader .file-list .file-item img{
         80px;
        height: 80px;
        border: 1px solid #ececec;
    }
    .vue-uploader .file-list .file-item .file-remove {
        position: absolute;
        right: 12px;
        display: none;
        top: 4px;
         14px;
        height: 14px;
        color: white;
        cursor: pointer;
        line-height: 12px;
        border-radius: 100%;
        transform: rotate(45deg);
        background: rgba(0, 0, 0, 0.5);
    }
    .vue-uploader .file-list .file-item:hover .file-remove {
        display: inline;
    }
    .vue-uploader .file-list .file-item .file-name {
        margin: 0;
        height: 40px;
        word-break: break-all;
        font-size: 14px;
        overflow: hidden;
        text-overflow: ellipsis;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
    }
    .vue-uploader .add {
         80px;
        height: 80px;
        margin-left: 10px;
        float: left;
        text-align: center;
        line-height: 80px;
        border: 1px dashed #ececec;
        font-size: 30px;
        cursor: pointer;
    }
    .vue-uploader .upload-func {
        display: flex;
        padding: 10px;
        margin: 0px;
        background: #f8f8f8;
        border-top: 1px solid #ececec;
    }
    .vue-uploader .upload-func .progress-bar {
        flex-grow: 1;
    }
    .vue-uploader .upload-func .progress-bar section {
        margin-top: 5px;
        background: #00b4aa;
        border-radius: 3px;
        text-align: center; 
        color: #fff;
        font-size: 12px;
        transition: all .5s ease;
    }
    .vue-uploader .upload-func .operation-box {
        flex-grow: 0;
        padding-left: 10px;
    }
    .vue-uploader .upload-func .operation-box button {
        padding: 4px 12px;
        color: #fff;
        background: #007ACC;
        border: none;
        border-radius: 2px;
        cursor: pointer;
    }
    .vue-uploader > input[type="file"] {
        display: none;
    }
    </style>

      效果:

  • 相关阅读:
    关于 flutter_boost splash加载动画
    [BS-23] AFN网络请求上拉/下拉刷新的细节问题总结
    [BS-22] Objective-C中nil、Nil、NULL、NSNull的区别
    [BS-21] 关于OC中对象与指针的思考
    [BS-20] 导航控制器和视图控制器在添加控制器的区别
    ios runtime swizzle
    关于C、OC、C++、OC++、Swift的一些常识
    iOS多线程知识总结--GCD
    使用代码创建AutoLayout约束
    iOS中NSLog输出格式大全
  • 原文地址:https://www.cnblogs.com/goloving/p/9236421.html
Copyright © 2011-2022 走看看