26

emmm我又来了๑乛◡乛๑

饿了么上传组件的文件列表filelist有个删除功能,我看源代码它是直接删除,并不会提示。issue上也有不少开发者提过这个问题,开发组还是建议自己写(想偷懒都不行……)
除了复写文件列表外,还加了一个上传状态的显示。

先上效果图:
文件列表

悬浮时的效果:
鼠标悬浮可点击放大删除

上传时的效果:
图片描述

以下测试在vue(v2.5) + vue-router(v3.0) + element-ui(v2.0)环境下进行,一些细节(如icon)会与上述图片不相符。所以每个步骤都加个图片=。=

步骤一:卡片化

其实就是重写样式,写个类似el-card组件的样式

<template>
    <div class="img-list">
        <div class="img-content" v-for="(item,key) in imagelist" :key="key">
            <img :src="item.url">
            <div class="name">
                <div>{{ item.name }}</div>
                <el-button type="text" @click="handleFileName(item,key)">修改名字</el-button>
            </div>
<!-- 删除icon -->
            <div class="del">
                <i @click="handleFileRemove(item,key)" class="el-icon-delete2"></i>
            </div>
<!-- 放大icon -->
            <div class="layer" @click="handleFileEnlarge(item.url)">
                <i class="el-icon-view"></i>
            </div>
        </div>
    </div>
</template>
<script>
export default{
    name: 'upload-list',
    data(){
        return {
            imagelist: [{
                url: 'http://img.hb.aicdn.com/723f8754f412debce188626d09cc0a1b2be6b7a6751a3-ICEp1E_fw658',
                name: 'lemon'
            },{
                url: 'http://img.hb.aicdn.com/38ab9e558bcba041be979f03bfd31bd67bf1e6f35815a-8PD8Eo_fw658',
                name: 'lemon2'
            },{
                url: 'http://img.hb.aicdn.com/0cd0dcc93f5b918e191dd84791101435136c7f9811e31-LRzYAQ_fw658',
                name: 'lemon3'
            }]
        }
    },
    methods: {
        handleFileEnlarge(_url){//放大图片
            console.log(_url)
        },
        handleFileName(file,i){//修改名字
            console.log(file,i)
        },
        handleFileRemove(file,i){//删除图片
            console.log(file,i)
        }
    }
}
</script>

放大按钮和删除按钮只有鼠标悬浮才显示:

*{
    box-sizing: border-box;
}
.img-list{
    overflow:hidden;
    width:100%;
}
.img-list .img-content{
    float:left;
    position:relative;
    display:inline-block;
    width:200px;
    height:270px;
    padding:5px;
    margin:5px 20px 20px 0;
    border:1px solid #d1dbe5;
    border-radius:4px;
    transition:all .3s;
    box-shadow:0 2px 4px 0 rgba(0,0,0,.12), 0 0 6px 0 rgba(0,0,0,.04);
}
.img-list .img-content img{
    display:block;
    width:100%;
    height:190px;
    margin:0 auto;
    border-radius:4px;
}
.img-list .img-content .name{
    margin-top:10px;
}
.img-list .img-content .name>div{
    width:90%;
    text-overflow:ellipsis;
    overflow:hidden;
    height:25px;
    line-height:25px;
}
.img-list .img-content:hover .del,
.img-list .img-content:hover .layer{
    opacity:1;
}
.img-list .img-content .del,
.img-list .img-content .layer{
    opacity:0;
    transition:all .3s;
}
.img-list .img-content .del{
    position:absolute;
    bottom:10px;
    right:10px;
    color:#8492a6;
    cursor:pointer;
    font-size:1.1em;
}
.img-list .img-content .layer{
    position:absolute;
    left:0;
    right:0;
    top:0;
    height:200px;
    color:#fff;
    text-align:center;
    z-index:5;
    background-color:rgba(0,0,0,.4);
}
.img-list .img-content .layer i{
    font-size:1.6em;
    margin-top:80px;
}

效果图:
步骤一效果图

步骤二:放大

这个操作很简单,用el-dialog组件

<div class="img-list">
    ...
    <el-dialog title="" :visible.sync="isEnlargeImage" size="large" :modal-append-to-body="false" top="8%" width="60%">
        <img @click="isEnlargeImage = false" style="width:100%;" :src="enlargeImage">
    </el-dialog>
</div>
<script>
export default{
    data(){
        return {
            isEnlargeImage: false,//放大图片
            enlargeImage: '',//放大图片地址
        }
    },
    methods: {
        handleFileEnlarge(_url){//放大图片
            console.log(_url)
            if(_url){
                this.enlargeImage = _url;
                this.isEnlargeImage = !this.isEnlargeImage;
            }
        }, 
    }
}
</script>

放大效果图

步骤三:删除和修改名字

emmm还是个简单的操作

handleFileRemove(file,i){//删除图片
    console.log(file,i)
    if(!file.url){
        return false;
    }
    let that = this;
    this.$confirm('是否删除此附件?','提示',{
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
    }).then(() => {
        //可添加ajax
        this.$message.success("删除成功")
        this.$message({
            type: 'success',
            message: '删除成功',
            onClose: () => {
                that.imagelist.splice(i,1)
            }
        })
    }).catch((meg) => console.log(meg))
},
handleFileName(file,i){//修改名字
    console.log(file,i)
    let that = this;
    this.$prompt("请输入新文件名:","提示:",{
        confirmButtonText: '确定',
        cancelButtonText: '取消'
    }).then(({ value }) => {
        console.log(value)
        if(!value){
            return false;
        }
        //可添加ajax
        this.$message.success("操作成功")
        that.imagelist[i].name = value
    }).catch(() => {})
},

效果图:
重新命名效果图

步骤四:上传进程

emmm其实这篇文章的重点在这儿。

css:

<style>
...
.img-list .img-upload{
    float:left;
    width:200px;
    height:270px;
    display:table;
    text-align:center;
}
.img-list .uploader{
    width:100%;
    display:table-cell;
    vertical-align:middle;
}
</style>
<template>
...
    <div class="img-upload">
        <el-upload class="uploader" accept="image/*"
          ref="upload"
          list-type="picture-card"
          :show-file-list="false"
          :action="params.action"
          :data="params.data"
          :on-change="uploadOnChange"
          :on-success="uploadOnSuccess"
          :on-error="uploadOnError"
          :on-progress="uploadOnProgress">
              <el-button type="primary">点击上传</el-button>
        </el-upload>
    </div>
</template>
<script>
...
data(){
    return {
        params: {
            action: 'http://jsonplaceholder.typicode.com/posts/',
            data: {}
        }
    }
},
...
methods: {
    uploadOnProgress(e,file){//开始上传
        console.log(e.percent,file)
    },
    uploadOnChange(file){
        console.log("——————————change——————————")
        // console.log(file)
        if(file.status == 'ready'){
            console.log("ready")
        }else if(file.status == 'fail'){
            this.$message.error("图片上传出错,请刷新重试!")
        }
    },
    uploadOnSuccess(e,file){//上传附件
        console.log("——————————success——————————")
        this.$message.success("上传成功")
    },
    uploadOnError(e,file){
        console.log("——————————error——————————")
        console.log(e)
    },
}
</script>

插播一则tips:在项目中文件是直接上传到阿里云,上传参数data会动态变化。但是由于自动上传一直出错(上传参数data有些关键字不存在),后来用手动上传却是可行。所以测试了半天才采用以下方式:

<el-upload :auto-upload="false"></el-upload>

methods:

uploadOnChange(file){
    if(file.status == 'ready'){
        this.params.data = {
            //change
        }
        this.$nextTick(() => {
            this.$refs.upload.submit();
        })
    }
}

加个上传加载的过程,el-progress组件恰好适用
css:

.img-list .img-progress{
    text-align:center;
    padding-top:50px;
}
<div v-if="!pass && progress !== 0" class="img-content img-progress">
    <el-progress type="circle" :percentage="progress" :status="proStatus"></el-progress>
</div>

data:

data(){
    return {
        progress: 0,//上传进度
        pass: null,//是否上传成功
    }
},
computed: {
    proStatus(){//上传状态
        if(this.pass){
            return 'success'
        }else if(this.pass == false){
            return 'exception'
        }else{
            return ''
        }
    }
},

methods:

uploadOnProgress(e,file){//开始上传
    console.log(e.percent,file)
    this.progress = Math.floor(e.percent)
},
uploadOnChange(file){
    console.log("——————————change——————————")
    // console.log(file)
    if(file.status == 'ready'){
        console.log("ready")
        //重置progress组件
        this.pass = null;
        this.progress = 0;
    }else if(file.status == 'fail'){
        this.$message.error("图片上传出错,请刷新重试!")
    }
},
uploadOnSuccess(e,file){//上传附件
    console.log("——————————success——————————")
    this.pass = true;
    this.$message.success("上传成功")
    this.imagelist.push({
        url: file.url,
        name: '新增图片'
    })
},
uploadOnError(e,file){
    console.log("——————————error——————————")
    console.log(e)
    this.pass = false;
},

原本是用this.progress控制status,但是后来发现及时上传进度100%也不一定上传成功,所以改用this.pass。用饿了么的上传地址偶尔会跨域报错,上传多几次又成了=。=

图片描述

图片描述

Github地址:点我点我点我(component/uploadlist.vue)


Shyla
1.5k 声望148 粉丝

FE programmer